this

调用位置

如果要从函数对象内部引用它自身,那只使用 this 是不够的。一般来说你需要通过一个指向函数对象的词法标识符(变量)来引用它。

  • 具名函数,在它内部可以使用 函数标识符 来引用自身。

  • 或使用 this 替代标识符 来引用函数对象(一般是没有名称标识符的匿名函数)。

  • 匿名函数对象 内部引用自身中 也可以使用 使用 arguments.callee 来引用当前正在运行的 函数对象

function foo(num) {
 console.log( "foo: " + num );
 // 记录 foo 被调用的次数
 // 注意,在当前的调用方式下(参见下方代码),this 确实指向 foo
 this.count++;
}
foo.count = 0;
var i;
for (i=0; i<10; i++) {
 if (i > 5) {
 // 使用 call(..) 可以确保 this 指向函数对象 foo 本身
 foo.call( foo, i );
 }
}
// foo: 6
// foo: 7
// foo: 8
// foo: 9

需要明确的是,this 在任何情况下都不指向函数的词法作用域。在 JavaScript 内部,作用域确实和对象类似,可见的标识符都是它的属性。但是作用域“对象”无法通过 JavaScript代码访问,它存在于 JavaScript 引擎内部。

this 指向函数的作用域 , 在某种情况下它是正确的,但是在其他情况下它却是错误的。

this 是在运行时进行绑定的,并不是在编写时绑定,它的上下文取决于函数调用时的各种条件。this 的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。

当一个函数被调用时,会创建一个活动记录(有时候也称为执行上下文)。这个记录会包含函数在哪里被调用(调用栈)、函数的调用方法、传入的参数等信息。this 就是记录的其中一个属性,会在函数执行的过程中用到。

this 实际上是在函数被调用时发生的绑定,它指向什么完全取决于函数在哪里被调用。

调用位置就是函数在代码中被调用的位置(而不是声明的位置)。 this 的绑定取决于调用栈中真正的调用位置的。

绑定规则

  1. 默认绑定
    最常用的函数调用类型:独立函数调用。

声明在全局作用域中的变量(比如 var a = 2)就是全局对象的一个同名属性。

function foo() { 
 console.log( this.a );
}
var a = 2;
foo(); // 2

可以看到当调用 foo() 时,this.a 被解析成了全局变量 a。函数调用时应用了 this 的默认绑定,因此 this 指向全局对象。 在代码中,foo() 是直接使用不带任何修饰的函数引用进行调用的,因此只能使用默认绑定,无法应用其他规则。

如果使用严格模式(strict mode),那么全局对象将无法使用默认绑定,因此 this 会绑定
undefined

function foo() { 
 "use strict";
 console.log( this.a ); 
}
var a = 2;
foo(); // TypeError: this is undefined

虽然 this 的绑定规则完全取决于调用位置,但是只有 foo() 运行在非 strict mode 下时,默认绑定才能绑定到全局对象;严格模式下与 foo() 的调用位置无关:

function foo() { 
 console.log( this.a );
}
var a = 2;
(function(){ 
 "use strict";
 foo(); // 2 
})();

通常来说你不应该在代码中混合使用 strict mode 和 non-strict mode。整个程序要么严格要么非严格。然而,有时候你可能会用到第三方库,其严格程度和你的代码有所不同,因此一定要注意这类兼容性细节。

  1. 隐式绑定
    调用位置是否有上下文对象,或者说是否被某个对象拥有或者包含,不过这种说法可能会造成一些误导。

你可能感兴趣的:(this)