JavaScript this - 全面解析 (二)

程序人生

2.2 绑定规则 - 隐式绑定

另一条需要考虑的规则是调用位置是否有上下文对象,或者说是否被某个对象拥有或者包含,不过这种说法可能会造成一些误导。
思考下面的代码:
function foo() {
    console.log( this.a );
}
var obj = {a: 2, foo: foo}; 
obj.foo();// 2
首先需要注意的是 foo() 的声明方式,及其之后是如何被当作引用属性添加到 obj 中的。 但是无论是直接在 obj 中定义还是先定义再添加为引用属性,这个函数严格来说都不属于 obj 对象。
然而,调用位置会使用 obj 上下文来引用函数,因此你可以说函数被调用时 obj 对象“拥有”或者“包含”它。
无论你如何称呼这个模式,当 foo() 被调用时,它的落脚点确实指向 obj 对象。当函数引 用有上下文对象时,隐式绑定规则会把函数调用中的 this 绑定到这个上下文对象。因为调 用 foo() 时 this 被绑定到 obj,因此 this.a 和 obj.a 是一样的。

回调函数丢失 this

<script type="text/javascript">
function foo(){
 setTimeout(function(){
  console.log(this.a);
 }, 1000);
}
var obj = {a:1, foo:foo};
obj.foo();
</script>
解决办法
<script type="text/javascript">
function foo(){
 var _this = this;
 setTimeout(function(){
  console.log(_this.a);
 }, 1000);}
var obj = {a:1, foo:foo};
obj.foo();
</script>
在一些流行的 JavaScript 库中事件处理器常会把回调函数的 this 强制绑定到触发事件的 DOM 元素上。 这在一些情况下可能很有用,但是有时它可能会让你感到非常郁闷。遗憾的是,这些工具 通常无法选择是否启用这个行为。

无论是哪种情况,this 的改变都是意想不到的,实际上你无法控制回调函数的执行方式, 因此就没有办法控制会影响绑定的调用位置。之后我们会介绍如何通过固定 this 来修复。

2.3 绑定规则 - 显式绑定

就像我们刚才看到的那样,在分析隐式绑定时,我们必须在一个对象内部包含一个指向函数的属性,并通过这个属性间接引用函数,从而把 this 间接(隐式)绑定到这个对象上。
那么如果我们不想在对象内部包含函数引用,而想在某个对象上强制调用函数,该怎么做呢?
JavaScript 中的“所有”函数都有一些有用的特性,可以用来解决这个问题。具体点说,可以使用函数的 call(..) 和 apply(..) 方法。严格来说,JavaScript 的宿主环境有时会提供一些非常特殊的函数,它们并没有这两个方法。但是这样的函数非常罕见,JavaScript 提供的绝大多数函数以及你自己创建的所有函数都可以使用 call(..) 和 apply(..) 方法。
这两个方法是如何工作的呢?它们的第一个参数是一个对象,它们会把这个对象绑定到 this,接着在调用函数时指定这个 this。因为你可以直接指定 this 的绑定对象,因此我们称之为显式绑定。
<script type="text/javascript">
function foo(){console.log(this.a);}
var obj = {a:1};
foo.call(obj);
</script>
通过 foo.call(..),我们可以在调用 foo 时强制把它的 this 绑定到 obj 上。
如果你传入了一个原始值(字符串类型、布尔类型或者数字类型)来当作 this 的绑定对象,这个原始值会被转换成它的对象形式(也就是 new String(..)、new Boolean(..) 或者 new Number(..))。这通常被称为“装箱”。
字符串例子:
<script type="text/javascript">
function foo(name){
 console.log(this + name);
}
var obj = {a:1};
foo.apply('....', ['hc']);
</script>
从 this 绑定的角度来说,call(..) 和 apply(..) 是一样的,它们的区别体现在其他的参数上。
<script type="text/javascript">
function foo(name){
 console.log(this.a + name);
}
var obj = {a:1};
foo.apply(obj, ['hc']);
</script>

Tags: JavaScript this
转自:http://www.hcoder.net/books/read/info/1218.html
*         

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