You Don't Know JS: this & Object Prototypes( 第2章 this)

this is a binding made for each function invocation, based entirely on its call-site (how the function is called).

this是为函数被引用而创建的绑定!完全地基于函数如何被调用/函数的call-site!


Call-site

:the location in code where a function is called

call-stack: 调用函数的堆栈。(函数的调用链条,函数的call-site的移动形成了stack。)

The call-site  is in the invocation before the currently executing function.

function baz() {
    // call-stack is: `baz`
    // so, our call-site is in the global scope

    console.log( "baz" );
    bar(); // <-- 下一个调用位置是‘bar‘
}

function bar() {
    // call-stack is: `baz` -> `bar`
    // so, 我们的call-site是在‘baz‘内。

    console.log( "bar" );
    foo(); // <-- call-site for `foo`
}

function foo() {
    // call-stack is: `baz` -> `bar` -> `foo`
    // so, our call-site is in `bar`

    console.log( "foo" );
}

baz(); // <-- call-site for `baz`

在浏览器inspector中,可以使用debugger工具观察call-site。

function baz() {
    console.log(this);
    console.log( "baz" );
    bar(); // <-- call-site for `bar`
}

function bar() {
    console.log(this)
    console.log( "bar" );
    foo(); // <-- call-site for `foo`
}

function foo() {
    console.log(this);
    console.log( "foo" );
}

baz();最后的结果是3个this都指向window对象。

Nothing But Rules

在函数执行期间,call-site如何决定this指向哪里?

有:4条法则!及这4条法则的优先级。

default Binding

第一条法则来自最常用的函数调用: 独立的函数引用。(没有其他法则影响的函数)

function foo() {
    console.log( this.a );
}

var a = 2;

foo(); // 2

this指向全局对象,变量a是全局对象的属性。

如果是严格模式,this指向undefined!

第一条:this绑定完全基于call-site,非严格模式下,全局对象是默认的绑定对象。

注意:不要混用严格模式和非严格模式!

Implicit Binding

第2条:如果call-site有一个context对象,也涉及一个拥有或包含的对象。

function foo() {
    console.log( this.a );
}

var obj = {
    a: 2,
    foo: foo
};

obj.foo(); // 2   因为obj就foo()调用的this, 所以this.a等同于obj.a

当有一个content object 拥有一个函数引用时,Implicit Binding Rule 就是那个对象应当拥有这个函数调用的this绑定

??:Only the top/last level of an object property reference chain matters to the call-site.

也就是说假如有:  obj1.obj2.obj3.foo(), 调用foo()函数的this绑定在obj3上。

Implicitly Lost

当一个Implicit bound 函数丢弃了context对象的binding, 就会使用默认binding。或用全局对象,或undefined(use strict)。

function foo() {
    console.log( this.a );
}

var obj = {
    a: 2,
    foo: foo
};

var bar = obj.foo; // function reference/alias!

var a = "oops, global"; // `a` also property on global object

bar(); // "oops, global"

obj.foo 结果是:
? foo() {
    console.log( this.a );
}
bar      //变量bar的值就是函数foo, 因为bar被分配了obj.foo结果是
? foo() {
    console.log( this.a );
}

所以: this指向全局对象window, this.a就是 window.a

另一个例子:参数传递

其实就是把obj.foo的值,分配给fn参数。等同于在doFoo函数内,声明了变量:var fn = obj.foo;

function foo() {
    console.log( this.a );
}

function doFoo(fn) {
    // `fn` is just another reference to `foo`

    fn(); // <-- call-site!
}

var obj = {
    a: 2,
    foo: foo
};

var a = "oops, global"; // `a` also property on global object

doFoo( obj.foo ); // "oops, global"

看到了吧: 结果this绑定的是全局对象。this.a就是window.a

JavaScript内建函数也同样:

function foo() {
    console.log( this.a );
}

var obj = {
    a: 2,
    foo: foo
};

var a = "oops, global"; // `a` also property on global object

setTimeout( obj.foo, 100 ); // "oops, global"

setTimeout()函数相当于:

function MySetTimeout(fn) {
    //0.1秒后;
    fn();
}

MySetTimeout( obj.foo )

函数回调丢失它们的this绑定是很常见的。

还有一类方式,是主动改变this:

Event handlers就会强制你的回调有一个this指向DOM中被激活的元素。

如果有一种方法可以固定住this,就好了!当然有了,见??,明确的绑定!

Explicit Binding

call()方法,apply()方法。第一个参数是一个对象的话,这个对象就绑定了this。

function foo() {
    console.log( this.a );
}

var obj = {
    a: 2
};

foo.call( obj ); // 2

??,call(..),apply(..)可接受多个参数,它们的用途这里不谈!

不幸的是,明确绑定,不能解决一个函数丢失它想要的this绑定的问题。

Hard Binding(explict and strong)

var bar = function() {
	foo.call( obj );
};

API Call "Contexts"

new Binding


Everything In Order

Determining this


Binding Exceptions

Ignored this

Safer this

Indirection

Softening Binding


Lexical this


Review (TL;DR)

4条rule

小心:

箭头函数

You Don't Know JS: this & Object Prototypes( 第2章 this)

原文地址:https://www.cnblogs.com/chentianwei/p/9744504.html

时间: 2024-07-30 03:02:19

You Don't Know JS: this & Object Prototypes( 第2章 this)的相关文章

You Don&#39;t Know JS: this &amp; Object Prototypes( 第3章 this和Object Prototypes)

前2章探索了this绑定指向不同的对象需要函数引用的call-site. 但是什么是对象,为什么我们需要指向它们? 本章探索细节. Syntax Type Build-in 对象 Contents Computed Property Names Property vs. Method Arrays Duplicating Objects Property Descriptors Writable Configurable Enumerable Immutability不变 Object Cons

You Don&#39;t Know JS: this &amp; Object Prototypes( 第一章 this or That?)

Foreword this 关键字和prototypes 他们是用JS编程的基础.没有他们创建复杂的JS程序是不可能的. 我敢说大量的web developers从没有建立过JS Object,仅仅对待这门语言作为一个事件绑定胶水,在按钮和Ajax请求之间. 我也曾是他们的一员,但是当我了解到如何掌握prototypes并创建JS对象,一个世界的可能性对我打开了. Chapter 1: this Or That? Chapter 2: this All Makes Sense Now! Chap

JS的Object漫想:从现象到“本质”

转自:http://zzy603.iteye.com/blog/973649 写的挺好,用于记录,把对象分成概念的Object(var f={})和 类的Object(function F(){}) ------------------------------------- 前言 首先,要说明的我是一个计算机爱好者,但我并不是科班出身,也没有受过专业的培训,所以,有些专业名词可能用的不当或者看法偏激乃至错误,敬请谅解并给予斧正为盼. 一.Object是什么? 刚开始我简单地认为Object是js

JS查看Object对象的内容

以一个例子来说,下面是他的Object: JS: 如果想直接获取到total的值,那就先把获取到的Json先Eval(),然后json.total就能取到total的值了, 但是如果想取到rows里面的值呢,我们先得进去rows,那就应该是:json.rows,但是我们alert的时候发现,这个rows有三个参数,我们要取第一个的话,那就应该是json.rows[0],然后再取 里面的strUserName或者strUserPwd就应该是Json.rows[0].strUserName了. 假设

JS与Object-C交互补充

有一个场景,用户点击Web页面,产生JS交互时,如何根据JS事件,App做出响应. 我们可以自己做一个简单的js交互,实现基于的原理是: 1. object-c利用stringByEvaluatingJavaScriptFromString:(NSString *)script消息获取uiwebview页面数据. 2. 那么如何监控特定的js事件呢?UIWebViewDelegate的(BOOL)webView:shouldStartLoadWithRequest:navigationType:

JS 对象(Object)和字符串(String)互转

JS 对象(Object)和字符串(String)互转 [javascript] view plaincopy var jsObj = {}; jsObj.testArray = [1,2,3,4,5]; jsObj.name = 'CSS3'; jsObj.date = '8 May, 2011'; var str = JSON.stringify(jsObj); alert(str); 从JSON字符串转为对象 [javascript] view plaincopy var jsObj = 

js 之 object

js之object 对象 ECMA-262 把对象(object)定义为"属性的无序集合,每个属性存放一个原始值.对象或函数".严格来说,这意味着对象是无特定顺序的值的数组. 尽管 ECMAScript 如此定义对象,但它更通用的定义是基于代码的名词(人.地点或事物)的表示. 类 每个对象都由类定义,可以把类看做对象的配方.类不仅要定义对象的接口(interface)(开发者访问的属性和方法),还要定义对象的内部工作(使属性和方法发挥作用的代码).编译器和解释程序都根据类的说明构建对象

js中object的申明方法

1 //js中的对象申明使用new Object(); 2 //object类型的数据类似于数组通过下表来访问其中的值 3 //example1 4 5 var person=new Object(); 6 person.name="张三"; 7 person.age="12"; 8 person.sex="男"; 9 10 for(var i in person){ 11 console.log(i+":"+person[i

js判断object的具体类型(或者说判断object的类class)

The JavaScript specification gives exactly one proper way to determine the class of an object: Object.prototype.toString.call(t); http://bonsaiden.github.com/JavaScript-Garden/#types https://stackoverflow.com/questions/7893776/the-most-accurate-way-t