关于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
来源:https://www.cnblogs.com/cyrus-br/p/10436552.html