this关键字详解
关于this的绑定
默认绑定 this 默认 绑定到 windows
-
在全局环境中,this默认绑定到 windows
-
函数独立调用时,this默认绑定到 windows
-
被嵌套函数独立调用时, this 默认绑定到 windows
-
IIFE 立即执行函数, 实际上是函数申明之后立即调用
-
闭包函数, 是独立调用,而不是方法调用。
var a = true; function fun(){ function test(){ console.log(a) } return test; } var o = { a : false; fun : fun; } o.fun()(); // true
由于闭包的this默认绑定到window对象,但又常常需要访问嵌套函数的this,所以常常在嵌套函数中使用var that = this,然后在闭包中使用that替代this,使用作用域查找的方法来找到嵌套函数的this值
var a = true; function fun(){ var that = this; // 用来记录 fun 的 this function test(){ console.log(that.a) } return test; } var o = { a : false; fun : fun; } o.fun()(); // false
隐式绑定
在方法调用时(被对象包含的函数,被对象直接调用时),this隐式的 绑定到该对象上。
```
var a = 0;
function fun(){
console.log(this.a)
}
var o = {
a : 1;
fun : fun;
}
o.fun() // 1
```
当对象嵌套时,依然是直接对象
```
var a = 0;
function fun(){
console.log(this.a)
}
var o1 = {
a : 1;
fun : fun;
o2:{
a : 2;
fun : fun;
}
}
// fun函数的直接对象o1
o1.fun() // 1
// fun函数的直接对象是O2
o1.o2.fun() // 2
```
显示绑定
通过 call() ,bind() ,apply() 方法, 把对象绑定到this上。叫做显示绑定。
```
var a = 1;
functiont fun(){
console.log(this.a)
}
var o = {
a : 0;
}
fun() // 1 独立调用
fun.call(obj); // 0
```
在javascript中新增了一些内置函数,具有显式绑定的功能,例如数组的迭代方法:map()、forEach()、filter()、some()、every()
```
var a = 'windows';
function fun(e){
console.log(e,this.id)
}
var o = {
a : 'o-object';
}
[1,2,3].forEach(fun) // 1 'windows' 2 'windows' 3 'windows'
// 当我们指定了绑定对象,this 就会改变
[1,2,3].forEach(fun,obj ) // 1 'o-object' 2 'o-object' 3 'o-object'
```
隐式丢失
指的是,隐式绑定的对象有时候会出现绑定对象的丢失,从而默认绑定到windows,主要是赋值操作。
- 函数别名
var a = 0;
function fun(){
console.log(this.a)
}
var o = {
a : 2;
fun : fun;
}
// 在这里出现赋值操作,使得o.fun 有了新的别名bar 造成了隐私丢失。
// 因为只是把fun函数赋给了foo,而foo与o对象则毫无关系。
var foo = o.fun;
- 参数传递
常见的一个例子:
var a = 0;
function fun(){
console.log(this.a);
}
var o = {
a : 1;
fun : fun;
}
// 其实 o.fun 在作为参数传递时候, 也是一个赋值操作。
// 同样的道理 只是把fun函数赋给了setTimeout 的一个形参 ,而与o对象则毫无关系。
setTimeout(o.fun,100) // 0
- 间接引用
function fun(){
console.log( this.a );
}
var a = 0;
var o1 = {a : 1, fun : fun};
var p2 = {a : 2};
o1.fun() // 1 方法调用
//将o1.fun函数赋值给o2.fun函数,然后立即执行。相当于仅仅是fun函数的立即执行
(o2.fun = o1.fun)();//0
// 注意上下两种的区别
o2.fun = o1.fun;
o2.fun() // 2
其实 在 javascript 内存角度上 O 和 o.fun 是存储在不同的地址上的。 只有o.fun() 才算是 从o 对象上去调用fun。否则,默认的是直接调用方法。因此绑定到了windows上。
(o2.fun = o1.fun)();//0
(false || 01.fun)();//0
(1, o1.fun)();//0
-
实现一个改变不了的this的绑定
利用显示绑定手段,可以是this不能被修改。就是将函数的调用封装起来 ,显示的绑定this对象。var a = 0; function fun(){ console.log(this.a) } var o = { a : 2; } var foo = function(){ fun.call(o) // 封装调用,显示绑定this对象 } foo() // 0 setTimeout(foo,100);//2 foo.call(window);//2