标签:独立 func ast mys 有一个 explicit voc 决定 another
this
is a binding made for each function invocation, based entirely on its call-site (how the function is called).
this是为函数被引用而创建的绑定!完全地基于函数如何被调用/函数的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对象。
在函数执行期间,call-site如何决定this指向哪里?
有:4条法则!及这4条法则的优先级。
第一条法则来自最常用的函数调用: 独立的函数引用。(没有其他法则影响的函数)
function foo() { console.log( this.a ); } var a = 2; foo(); // 2
this指向全局对象,变量a是全局对象的属性。
如果是严格模式,this指向undefined!
第一条:this绑定完全基于call-site,非严格模式下,全局对象是默认的绑定对象。
注意:不要混用严格模式和非严格模式!
第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上。
当一个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,就好了!当然有了,见??,明确的绑定!
call()方法,apply()方法。第一个参数是一个对象的话,这个对象就绑定了this。
function foo() { console.log( this.a ); } var obj = { a: 2 }; foo.call( obj ); // 2
??,call(..),apply(..)可接受多个参数,它们的用途这里不谈!
不幸的是,明确绑定,不能解决一个函数丢失它想要的this绑定的问题。
var bar = function() {
foo.call( obj );
};
new
Binding
this
this
this
this
4条rule
小心:
箭头函数
You Don't Know JS: this & Object Prototypes( 第2章 this)
标签:独立 func ast mys 有一个 explicit voc 决定 another
原文地址:https://www.cnblogs.com/chentianwei/p/9744504.html