区别
箭头函数和普通函数之间最关键的区别是this指向问题。普通函数中的 this
指向函数被调用的对象,因此对于不同的调用者,this
的值是不同的。
箭头函数中并没有自己的 this
,所以箭头函数中的 this
是固定的,指向定义函数时所在的对象。
普通函数
var a = 3;
var obj = {
a:1,
foo:function(){
console.log(this.a);
}
}
obj.foo(); // 1;
var fn = obj;
fn.a = 100;
fn.foo();//100
var f = obj.foo;
f(); // 3
根据这段代码可以知道,普通函数中的 this
总是指向它的调用者,在严格模式下,没找到调用者,函数中的 this
是 undefined
。在非严格模式下,没找到调用者 this
指向 window
。
var obj = {
a:1,
foo:function(){
setTimeout(function(){
console.log(this.a,this)
},100)
}
}
obj.foo();//undefined,window
这段代码中,setTimeout
中的 function
没被任何对象调用,所以 this
指向还是 window
对象。
如果想要将在 setTimeout
中的 this
指向 obj。在箭头函数之前,通常有2种方法。
定义一个临时变量
在 foo 函数的内部,通过定义一个变量 that
来保存当时的 this
。
var obj = {
a:1,
foo:function(){
var that = this;
setTimeout(function(){
console.log(that.a,that)
},100)
}
}
obj.foo();//1, {a: 1, foo: ƒ}
使用bind()来绑定this
var obj = {
a:1,
foo:function(){
setTimeout(function(){
console.log(this.a,this)
}.bind(this),100)
}
}
obj.foo();//1, {a: 1, foo: ƒ}
箭头函数
箭头函数是 ES6 中引入的新特性。箭头函数表达式的语法比函数表达式要简洁,并且没有自己的 this
、arguments
、super
、new.target
。更适于那些本来需要匿名的函数,并且箭头函数不可以作为构造函数。其语法为:
(参数1,参数2,...,参数N) =>{ 函数体 }
// 相当于(参数1,参数2,...,参数N) =>{ return 表达式; }
(参数1,参数2,...,参数N) => 表达式(单一)
//当只有1个参数,可忽略()
(参数)=>{ 函数体 }
参数 =>{ 函数体 }
//没有参数的函数写成一个()
()=>{ 函数体 }
高级语法
返回对象字面量表达式
用 params=>{object: literal}
这种简单的语法返回对象字面量是行不通的。
var func = ()=>{ obj: 1 }; // 调用 func() 返回 undefined
var func = ()=>{ foo: function(){} } //Function statements require a function name
这是因为花括号 {}
里面的代码被解析为一系列语句 ( foo 被认为是一个标签,而非对象字面量的组成部分 )。所以不要忘记用 ( )
把对象字面量包括起来。
name=>({obj:name})
支持剩余参数和默认参数
(参数1, 参数2, ...rest) => {函数声明}
(参数1 = 默认值1,参数2, …, 参数N = 默认值N) => {函数声明}
支持参数解构
let f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c;
f(); // 6
箭头函数有2个方面的作用: 简短的函数和不绑定this
简短的函数
var ary = [1,2,3,4];
ary.map(item=>{
return item
})// [1, 2, 3, 4]
箭头函数式闭包
var add = (i=0)=>{ return (()=>(i+10))}
add(10)(); // 20
不绑定 this
箭头函数不会自己创建 this
,只会从自己作用域链的上一层继承 this
,因此下面 setTimeout 里面函数的 this
和 foo 函数的 this
是相同的。
var a = 100;
var obj = {
a:1,
foo:function(){
setTimeout(()=>{
console.log(this.a,this); //正确的执行当前函数执行的上下文
},100)
}
}
obj.foo();//1,{a: 1, foo: ƒ}
没有 arguments
对象
let u = ()=>{
console.log(arguments)
}
u(1,2,3); // arguments is not defined
function foo(n) {
var f = () => arguments[0] + n; // 隐式绑定 foo 函数的 arguments 对象. arguments[0] 是 n
return f();
}
foo(1); //2
不能够使用 new
操作符
let B = ()=>{}
let b = new B(); // B is not a constructor
没有 prototype
属性
let B = ()=>{}
B.prototype; // undefined
yield
关键字通常也不在箭头函数中使用( 除非是嵌套的在允许使用的函数内 ),所以箭头函数不能用作生成器。