0x01:this究竟指向什么?
普通函数的this
简单的法则:
- 有对象就指向调用对象
- 没调用对象就指向全局对象
- 用new构造就指向新对象
- 通过 apply 或 call 或 bind 可以改变this的指向
简单的例子:
var name = 'global';
var ob = {
name: 'ob1',
getName_1: function(){
console.log(name);
},
getName_2: function(){
console.log(this.name);//this指向调用的对象
}
}
var getName_3 = ob.getName_2;
ob.getName_1();//global
ob.getName_2();//ob1,因为函数的调用对象是ob
getName_3();//global,因为调用对象是window
js只有函数作用域,没有块级作用域,因此定义在对象中的属性在对象的函数中并不能直接查找到。
箭头函数的this
参考资料:MDN:箭头函数
然而伴随着 ECMAScript 诞生的箭头函数在 this 的处理与以往不同。箭头函数并非单纯的匿名函数语法糖,匿名函数的this
指向全局对象(浏览器中应该是window),而箭头函数的this
是指向定义该函数时所在上下文的this,举个例子:
var ob1 = {
birth: 1990,
getAge: function (year) {
var fn = function(y){
return y - this.birth; // this指向window或undefined
};
return fn(year);
}
};
var ob2 = {
birth: 1990,
getAge: function (year) {
var fn = (y) => y - this.birth; // this.birth为1990
return fn(year);
}
};
在调用ob1.getAge(2018)
的时候,getAge 中直接调用了 fn,此时 fn 中的this
指向 window。而在ob2中,定义fn这个箭头函数的时候,fn所在的上下文中this
其实是 getAge 的this
,即 ob2。
箭头函数不能通过 call/apply/bind 修改
this
.
0x02:普通函数的 call / apply / bind
Function.prototype.apply()
在 Javascript 中每个函数都有两个非继承来的方法:call()
和allpy()
。通过调用这两个方法可以使该函数在特定的作用域中执行,也就意味着this
的变化。同时这两个方法被用于设定函数运行的作用域。
语法
fun.apply(thisArg[, argsArray])//第一个参数是设定的this值,第二个参数是传给该函数的参数数组
fun.call(thisArg, arg1, arg2,...)//与apply不同的地方在于参数一一列出
fun.bind(thisArg[, arg1[, arg2[, ...]]])//ECMA5新增
设定作用域的例子
var color = 'red';//也即window.color
var ob = {color:'blue'};
function getColor(){
console.log(this.color);
}
getColor();//red
getColor.call(ob);//blue
var getInstanceColor = getColor.bind(ob);
getInstanceColor();//blue