最近看《你不知道的js(上卷)》关于this的个人理解加总结:
这本书对于我理解this真的起到了非常大的作用,,,以前看的比较杂乱。。摁,感觉现在很清晰。摁,废话了。
文中有不少自己的话描述的部分,有不对的地方还请批评指正。
首先,this的绑定跟调用位置是有非常大的关系的。
然后,重点来了。。
this的绑定对象有四大种情况:
一、默认绑定
二、隐式绑定
三、显示绑定
四、new绑定
一、默认绑定:通过独立函数调用。
function foo() {
console.log(this.a);}
var a=2;foo();//2
需要注意的有几点:
1、声明在全局作用域中的变量就是全局对象的一个同名属性(例如,本例中var a=2;即window.a=2);
2、foo是直接使用不带任何修饰的函数引用进行调用的,因此只能是默认绑定。
3、如果使用严格模式(strict mode),则不能将全局对象用于默认绑定,因此this会绑定到undefined。
关于第3点举例如下:
function foo() {"use strict";console.log(this.a);}
var a=2;foo();该代码段输出结果如下:
但是,
function foo() {
console.log(this.a);
}
var a=2;
"use strict";
foo();//2
或者
function foo() {
console.log(this.a);
}
var a=2;
(function () {
"use strict";
foo();//2
})();
会正常的输出2.则 说明 foo运行在严格模式下时,默认绑定不能绑定到全局对象;如果在严格模式下调用的话,foo则不影响默认绑定,即它仍然可以绑定到全局对象。(注意一个是运行环境,一个是调用环境)。
注意:将"use strict"放在脚本文件的第一行,则整个脚本都将以"严格模式"运行;所以放在下面或者放到自执行函数里面。
二、隐式绑定
看调用位置是否有上下文对象,或者说被某个对象拥有或者包含。(可能这种说法也不太严格)
上代码:
function foo() {
console.log(this.a);
}
var obj={
a:2,
foo:foo
};
obj.foo();//2
1、
函数引用有上下文对象时,隐式绑定规则会把函数调用中的this绑定到这个上下文对象。
2、foo只是被当作引用属性添加到obj中的,无论foo直接在obj中定义或者先定义再添加为引用属性,这个函数严格来说都不属于obj对象(这大概是给下面的隐式丢失埋下伏笔吧。。。)。
3、对象属性引用链中只有上一层或者说最后一层在调用位置中起作用(如下代码)。
function foo() { console.log(this.a); } var obj2={ a:42, foo:foo }; var obj1={ a:2, obj2:obj2 }; obj1.obj2.foo();//42
然尔。。。隐式绑定的话,就会出现隐式丢失的情况:三种隐式丢失的情况。
隐式丢失就是函数丢失了绑定对象,此时他会应用默认绑定(也就是第一大种绑定方式),把this绑定到全局对象或者undefined上,取决于是否是严格模式。
一一:给函数起别名:
上代码:
(这个地方会丢失的原因大概是后面属性与方法中讲的,,,从技术角度说,函数永远不会“属于”一个对象!有时候this确实会指向调用位置的对象引用,但是这种用法从本质上来说并没有把一个函数变成一个“方法”。即并不是对象调用了这个函数,这个函数就是它的了。。。。。也并不能说明函数是特别的或者“属于”某个对象。。。。。)function foo() { console.log(this.a); } var obj={ a:2, foo:foo }; var bar=obj.foo; //给函数起别名 var a="绑到全局对象了";//a是全局对象的属性 bar();//输出:绑到全局对象了
1、虽然bar是obj.foo的一个引用,但实际上,它引用的是foo函数本身,此时的bar()其实是一个不带任何修饰的函数调用,因此应用默认绑定。
二二:作为参数传入自己声明的函数:
上代码:doFoo是自己声明的函数嘛
function foo() {
console.log(this.a);
}
function doFoo(fn) {
fn();
}
var obj={
a:2,
foo:foo
};
var a="绑到全局对象了";
doFoo(obj.foo);//输出:绑到全局对象了
参数传递其实就是一种隐式赋值,因此我们传入函数时也会被隐式赋值,所以结果跟一一一样。
三三:作为参数传入语言内置的函数
setTimeout是javascript内置的全局函数嘛
上代码:
显示绑定跟new绑定明天再说吧。。。。。这三种就是最常见的this指向丢失的情况了。function foo() { console.log(this.a); } var obj={ a:2, foo:foo }; var a="绑到全局对象了"; setTimeout(obj.foo,100);//输出:绑到全局对象了