JavaScript this - 全面解析 (一)

程序人生
在第1节中,我们排除了一些对于 this 的错误理解并且明白了每个函数的 this 是在调用 时被绑定的,完全取决于函数的调用位置(也就是函数的调用方法)。

调用位置

在理解 this 的绑定过程之前,首先要理解调用位置:
调用位置就是函数在代码中被调用的位置(而不是声明的位置)。只有仔细分析调用位置才能回答这个问题:这个 this 到底引 用的是什么?
通常来说,寻找调用位置就是寻找“函数被调用的位置”,但是做起来并没有这么简单, 因为某些编程模式可能会隐藏真正的调用位置。
最重要的是要分析调用栈(就是为了到达当前执行位置所调用的所有函数)。我们关心的调用位置就在当前正在执行的函数的前一个调用中。
下面我们来看看到底什么是调用栈和调用位置:
<script type="text/javascript">
function baz() {
 // 当前调用栈是:baz
 // 因此,当前调用位置是全局作用域 
    console.log( "baz" );
    bar(); // <-- bar 的调用位置
}
function bar() { 
    // 当前调用栈是 baz -> bar
    // 因此,当前调用位置在 baz 中 
    console.log( "bar" );
    foo(); // <-- foo 的调用位置
}
function foo() {
 // 当前调用栈是 baz -> bar -> foo
 // 因此,当前调用位置在 bar 中
    console.log( "foo" );
} 
baz(); // <-- baz 的调用位置
</script>
注意我们是如何(从调用栈中)分析出真正的调用位置的,因为它决定了 this 的绑定。
你可以把调用栈想象成一个函数调用链,就像我们在前面代码段的注释中所 写的一样。但是这种方法非常麻烦并且容易出错。另一个查看调用栈的方法 是使用浏览器的调试工具。绝大多数现代桌面浏览器都内置了开发者工具, 其中包含 JavaScript 调试器。就本例来说,你可以在工具中给 foo() 函数的 第一行代码设置一个断点,或者直接在第一行代码之前插入一条 debugger; 语句。运行代码时,调试器会在那个位置暂停,同时会展示当前位置的函数调用列表,这就是你的调用栈。因此,如果你想要分析 this 的绑定,使用开发者工具得到调用栈,然后找到栈中第二个元素,这就是真正的调用位置。

2.1 绑定规则 - 默认绑定

首先要介绍的是最常用的函数调用类型:独立函数调用。可以把这条规则看作是无法应用其他规则时的默认规则。
思考一下下面的代码:
function foo(){
    console.log(this.a);
}

var a = 2;
foo(); // 2
你应该注意到的第一件事是,声明在全局作用域中的变量(比如 var a = 2)就是全局对 象的一个同名属性。它们本质上就是同一个东西,并不是通过复制得到的,就像一个硬币的两面一样。
接下来我们可以看到当调用 foo() 时,this.a 被解析成了全局变量 a。为什么?因为在本例中,函数调用时应用了 this 的默认绑定,因此 this 指向全局对象。
那么我们怎么知道这里应用了默认绑定呢?可以通过分析调用位置来看看 foo() 是如何调用的。在代码中,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。整个 程序要么严格要么非严格。然而,有时候你可能会用到第三方库,其严格程度和你的代码有所不同,因此一定要注意这类兼容性细节。
Tags: JavaScript this
转自:http://www.hcoder.net/books/read/info/1217.html
  • 还没有评论,沙发等你来抢
*         

正在加载验证码......