先来看一段代码:
var func = new function) {
this.a = "func";
}
// var func2 = functionx) {
// var a = "func2";
// alertthis.a); // func
// alertx); // func2
// }
// 箭头函数this指向对象本身
let func2 = x => {
let a = 'func2';
alertthis.a) // undefined
alertx) // func2
}
// call改变this指向,将func2的this指向func
func2.callfunc, "func2");
一、什么是箭头函数,为什么使用箭头函数?
箭头函数就是函数的一种简写形式,使用括号包裹参数,跟随一个=>,紧接着是函数体。
ES6中,箭头函数的引入有两个方面的作用:一是更简短的函数书写,二是对this的词法解析。
二、箭头函数的this
箭头函数没有它自己的this
值,箭头函数内的this
值继承自外围作用域。
this
指向的固定化,并不是因为箭头函数内部有绑定this
的机制,实际原因是箭头函数根本没有自己的this
,导致内部的this
就是外层代码块的this
。正是因为它没有this
,所以也就不能用作构造函数。
var col = 3
var obj = {
col: 5,
show: function ) {
console.logthis.col)
}
}
obj.show) // 5
分析:
调用者是obj,所以this指向obj
var col = 3
var obj = {
col: 5,
show: ) => console.logthis.col)
}
obj.show) // 3
分析:
因为是箭头函数,var定义的obj,作用域在全局,所以此时的this指向window
let col = 3
let obj = {
col: 5,
show: ) => console.logthis.col)
}
obj.show) // undefined
分析:
因为是let声明,let、const、class命令声明的全局变量是不属于顶层对象的属性的,所以,this就既不指向window,也不指向obj
function Person) {
// 构造函数 Person) 定义的 `this` 就是新实例对象自己
this.age = 0;
setIntervalfunction growUp) {
// 在非严格模式下,growUp) 函数定义了其内部的 `this`为全局对象,
// 不同于构造函数Person)的定义的 `this`
this.age++;
}, 3000);}
var p = new Person);
上面定时器的this并不是指向构造函数的this,这并不是我们想要的。所以想要定时器里面的this指向构造函数,我们可以通过把this的值赋值给变量,然后将该变量放到闭包中来解决。
function Person) {
var self = this;
// 也有人选择使用 `that` 而非 `self`, 只要保证一致就好.
self.age = 0;
setIntervalfunction growUp) {
// 回调里面的 `self` 变量就指向了期望的那个对象了
self.age++;
}, 3000);}
var p = new Person);
我们还可以使用bind函数,把期望的this值传递给growUp函数。当然,我们可以使用箭头函数轻松实现,箭头函数会捕获他所在的上下文的this值,作为自己的this值。
function Person) {
this.age = 0;
setInterval) => {
// 回调里面的 `this` 变量就指向了期望的那个对象了
this.age++;
}, 3000);}
var p = new Person);
call和apply调用对箭头函数this的影响:
var adder = {
base : 1,
add : functiona) {
var f = v => v + this.base;
return fa);
},
addThruCall: functiona) {
var f = v => v + this.base;
var b = {
base : 2
};
return f.callb, a);
}};
console.logadder.add1)); // 输出 2
console.logadder.addThruCall1)); // 仍然输出 2(而不是3 ——译者注)
分析如下:
1、adder.add1)执行add函数,add返回fa)也就是f1)的调用,执行f)函数,f是箭头函数写法,this.base中的this指向对象本身,所以输出2
2、adder.addThruCall1)执行addThruCall,返回f.callb, a),call本质是将f的this指向b,所以此时的this.base理应是2,但是因为是箭头函数的写法,this已经在词法层面完成了绑定,通过call或者apply方法调用的时候,只是出入了参数,并没有改变this的指向,所以此时的值还是2.
三、arguments
箭头函数不会在其内部暴露出参数,也就是说没有自己的arguments:
var arguments = 42;var arr = ) => arguments;
arr); // 42
function foo) {
var f = i) => arguments[0]+i;
// foo函数的间接参数绑定
return f2);}
foo1); // 3
不过在大多数情形下,rest参数可以给出一个解决方案:
function foo) {
var f = ...args) => args[0];
return f2);
}
foo1);
// 2
四、注意事项
1、箭头函数不能用作构造器,和new一起用就会报错
var Foo = ) => {};
var foo = new Foo);
// TypeError: Foo is not a constructor
2、箭头函数没有原型属性
var Foo = ) => {};
console.logFoo.prototype);
// undefined
3、箭头函数既支持简写也支持常规编写
var func = x => x * x;
// 简写函数 省略return
var func = x, y) => { return x + y; };
//常规编写 明确的返回值