var a = 1;
var foo = {
a: 2,
bar: function () {
return this.a;
}
};
console.log(foo.bar()); //2
console.log((foo.bar)()); //2
console.log((foo.bar=foo.bar)()); //1
“匿名函数的执行环境具有全局性”,所以最里层那个函数中this指向全局环境,全局环境没有定义foo变量所以输出undefined。在匿名函数外部将this保存到一个内部函数可以访问的变量self中,可以通过self访问这个对象,所以self.foo为bar
var myobject = {
foo: “bar”,
func: function () {
var self = this;
console.log(this.foo);
console.log(self.foo);
(function () {
console.log(this.foo);//undefined
console.log(self.foo);//bar
})();
}
};
myobject.func();
改变this指向
JavaScript为我们专门提供了一些函数方法来帮助我们处理函数内部this指向问题,常用的有bind()、call()、apply()
三种方法
1.call()
前面讲过,call的主要作用可以实现继承
var obj = {
a:1
}
function f(){
console.log(this);
}
f.call(obj)
//call 第一个可以调用函数,还可以改变函数类this指向
//call 主要作用可以实现继承
2.apply()
方法调用一个函数,简单理解为调用函数的方式,但是它可以改变this的指向
fun.apply(thisArg, [argsArray])
thisArg:在函数执行时指定的this对象
argsArray: 传递的值,必须包含在数组(伪数组)里面
返回值为函数的返回值,因为它就是调用函数
应用方面:apply传递数组参数,所以可以借助数学内置对象求最大值 Math.max.apply(Math,arr)
var arr = [1,66,199,5,6]
//console.log(Math.max.apply(null,arr));
//严格模式,最好让thisArg指向Math
console.log(Math.max.apply(Math,arr));
//求数组最大值的其他方法
var ma = Math.max(…arr);
(es6拓展运算符…Math.max(...arr)
也可以,但是不能 MAth.max(arr)
,因为max不接受数组,只接受一个一个的参数)
3.bind()
方法不会调用函数
,但是能改变函数内部this指向
fun.bind(thisArg, arg1, arg2…)
返回指定this值和初始化参数改造的原函数拷贝
即创造新的函数 var f = fn.bind(xx)
应用方面:定时器等不想立即调用的函数(或者处理其他只能用that来暂时储存对象的情况)
//场景:点击按钮后,禁用按钮。3秒后恢复
btn.onclick = function() {
this.disabled = true;
//old way:
var that = this;
setTimeout(function() {
that.disabled = false;
}, 3000)
//new way:
setTimeout(function() {
this.disabled = false;
}.bind(this), 3000) //这个this指向btn
}
巧妙运用: 传参的时候可以传递其他对象过来
call、apply、bind总结
相同
:改变函数内部的this指向。
区别
:
-
call和apply会调用函数,bind不调用但返回一个改造过this的函数。
-
call和bind传参为aru1,aru2…形式,apply必须数组形式[arg]
应用
:
-
call经常做继承
-
apply经常与数组有