持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第4天,点击查看活动详情
用法
let add = function (a, b) {
return a + b;
};
箭头函数写法
let add = (a, b) => a + b;
// 返回一个对象
let objFn = (key, val) => ({ [key]: val });
objFn('a', 1);
// {a: 1}
与普通函数的区别
1. 没有 this
对于普通函数来说,内部的 this 指向函数运行时所在的对象,而箭头函数没有 this,所以需要通过查找作用域链来确定 this 的值。
function foo() {
setTimeout(() => {
console.log('name:', this.name);
}, 100);
}
var name = '小白';
foo.call({ name: '白菜' }); // 白菜
这里 setTimeout 使用了箭头函数, this 在 foo 函数调用的时候指向 { name: '白菜'}
如果是普通函数,则会输出 '小白', 普通函数指向 window
上面的代码经过 Babel 转换之后的代码
// ES5
function foo() {
var _this = this;
setTimeout(function () {
console.log('name:', _this.name);
}, 100);
}
dom 中的使用
再比如说,我们在封装 Button组件的时候
// 传入id 点击需要做一些事情的时候
new Button("button")
// html
<button id="button">doSomething</button>
// js
function Button(id) {
this.element = document.querySelector("#" + id);
this.bindEvent();
}
Button.prototype.bindEvent = function() {
this.element.addEventListener("click", this.doSomething, false);
};
Button.prototype.doSomething = function() {
console.log('to do')
console.log('this.element :>> ', this.element);
// 例如修改苦读
this.element.style.width = '200px'
};
var button = new Button("button");
我们运行看下结果
看着没啥问题,运行的时候发现,this.element 居然是 undefined ,
这是因为当使用 addEventListener() 为一个元素注册事件的时候,事件函数里的 this 值是该元素的引用,即 doucument 对象 button ,而我们在 function 里面定义的 this.element 才是 document 对象
当然你可以
Button.prototype.doSomething = function () {
this.style.width = '200px';
};
嗯, 看着似乎是没啥问题,程序也能跑,但是如果你要在里面做一些其他操作呢?
Button.prototype.doSomething = function () {
this.InitW();
};
function InitW() {
this.style.width = '200px';
}
这个时候使用 this 不是就不行了嘛。所以呢我们还是希望 doSomething 中的 this 是指向实例对象的,这样就可以调用其他的函数了。
为了避免这种情况发生我们一般使用 bind 去强制绑定 doSomething 的 this 为实例对象。
当然我们使用 ES6 的箭头函数也能更好的解决这个问题
Button.prototype.bindEvent = function () {
this.element.addEventListener(
'click',
(event) => this.doSomething(event),
false
);
};
由于箭头函数没有 this ,因此它会向外层查找,即 bindEvent 中的 this ,此时 this 指向实例对象。
bind,call,apply 中的使用
function foo() {
return () => {
return () => {
console.log('id:', this.id);
};
};
}
var f = foo.call({ id: 1 });
var t1 = f.call({ id: 2 })()(); // id: 1
var t2 = f().call({ id: 3 })(); // id: 1
var t3 = f()().call({ id: 4 }); // id: 1
上面程序里面的 this 指向只有一个就是 foo 函数中的 this ,不管嵌套多少层,由于使用的都是箭头函数,所以他的 this 指向并不会发生改变。
2. 没有 arguments
function fn() {
return () => arguments[]
}
var result = fn(1,3,4);
console.log(result()); // Arguments(3) [1, 3, 4, callee: ƒ, Symbol(Symbol.iterator): ƒ]
箭头函数虽然没有自己的 arguments ,但是它却可以访问外层的 arguments
3. 不能通过 new 关键字调用
var fn = () => {};
var foo = new fn(); // TypeError: fn is not a constructor
上面的程序报错了,是因为在 JavaScript 里面,函数有两个内部方法:Call 和 Construct。
当函数通过 new 调用的时候,执行 Construct 方法,先创建一个实例对象,再执行函数体,然后将 this 绑定到实例上。
因为箭头函数没有 this ,箭头函数并没有 Construct,不能被用作构造函数,当通过 new 掉用的时候会报错。
4. 没有原型,new.target,super
由于不能使用 new 调用箭头函数,所以也不能构建原型,也就是说没有 prototype 这个属性。
没有原型的话,那当然也不能通过 super 来访问原型的属性
因为不能使用 new 调用,所以也没有 new.target 值。
5. 不能用作 Generator 函数
不可以使用 yield 命令,因此箭头函数不能用作 Generator 函数。
关于 Generator 函数,见 Generator