ES6箭头函数
写在前面
-
箭头函数是不能new的,它的设计初衷就跟构造函数不太一样
-
箭头函数如果要返回一个JSON对象,必须用小括号包起来 var test = ()=>({id:3, val=20})
-
箭头函数没有prototype原型,所以箭头函数本身没有this
-
箭头函数的this在定义的时候继承自外层第一个普通函数的this
-
如果箭头函数外层没有普通函数,严格模式和非严格模式下它的this都会指向window(全局对象)
-
箭头函数本身的this指向不能改变,但可以修改它要继承的对象的this。
-
箭头函数的this指向全局,使用arguments会报未声明的错误。
-
箭头函数的this指向普通函数时,它的argumens继承于该普通函数
-
箭头函数不支持new.target
-
箭头函数不支持重命名函数参数,普通函数的函数参数支持重命名
-
对代码的可读性伤害太大
1.箭头函数语法
原有方法的声明函数
//function普通函数
function fn(a, b){
return a + b;
}
console.log(fn(1,2))
//或
var fn = function(a){
return a + 1
}
箭头函数语法
(参数1, 参数2, …, 参数N) => { 函数声明statements }
(参数1, 参数2, …, 参数N) => 表达式expression(单一)
//相当于:(参数1, 参数2, …, 参数N) =>{ return 表达式expression; }
// 当只有一个参数时,圆括号是可选的:
(单一参数) => {函数声明statements}
单一参数 => {函数声明statements}
// 没有参数的函数应该写成一对圆括号
() => {函数声明statements}
//返回一个对象时,函数体外要加圆括号
params => ({foo:bar})
//支持剩余参数和默认参数
(参数1, 参数2, …rest) => { 函数声明statements }
// …rest参数,必须是参数列表最后一个参数
(param1 = defaultValue1, param2, …, paramN = defaultValueN) => { 函数声明statements }
//支持参数列表中的结构赋值
let fn = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c; // a=1; b=2; x=c; c=a+b=3;
fn(); // 6
注:如果不加{},则默认使用return
箭头函数写法:var 函数名 = 参数 => 运算规则
//多个参数需要用到小括号,参数间逗号间隔
var foo = (a, b)=>{ return a + b };
console.log(foo(4,5))
//或,省略了function、return关键字和大括号
var a = (a) => a + 1;
//或,没有参数的需要用在箭头前加上小括号
var b = () => alert('Hello')
//或,有参数的箭头函数
var c = (abc) =>{
console.log(abc)
}
c('World')
注:省略{}相当于给了一个return;有{}必须return 外面才能接收到返回的值
当作为事件handler,给click绑定箭头函数:
var obj = document.getElementById('goods');
//DOM1级绑定
obj.onclick = function(){}
obj.onclick = ()=>{
alert('Hello');
}
//DOM2级
var fn = ()=>{
alert('World');
}
obj.addEventListener('click',fn);
2.不支持new操作符
箭头函数不能用作构造器,使用new就会抛出错误
var fn = ()=>{}
var Fn = new Fn() //test.html:204 Uncaught TypeError: Fn is not a constructor
3.没有原型属性
箭头函数没有原型属性
var fn = () => {};
console.log(fn.prototype); // undefined
4.使用yield关键字
yield 关键字通常不能在箭头函数中使用(除非是嵌套在允许使用的函数内)。因此,箭头函数不能用作生成器。
5.返回文字表达式
错误写法
var fn = () => {foo:1};
var Fn = () =>{foo:function(){}}
正确写法
var fn = () => ({foo:1});
6.不允许换行
箭头函数在参数和箭头函数之间不能换行
var fn = ()
=> 1; //Uncaught SyntaxError: Unexpected token =>
7.解析顺序
箭头函数的解析规则是相比普通的函数,受操作符的优先级影响,箭头函数的解析顺序相对靠前
8.this指向
1.箭头函数的this指向定义时所在的外层第一个普通函数,跟使用位置没有关系。2.被继承的普通函数的this指向改变,箭头函数的this指向会跟着改变
3.不能直接修改箭头函数的this指向
普通函数:
var a = {
num: 9,
decrease: function() {
this.num--
console.log(this) //{num: 8, decrease: ƒ},{num: 7, decrease: ƒ}
}
}
a.decrease()
a.decrease()
console.log(a.num) //7
call apply bind依旧不能改变this指向
window.num = '1'
let num = '2'
let obj = {
num: '3'
}
let sayNum = function() {
return this.num
}
console.log(sayNum.call(obj)) //3
箭头函数:
var a = {
num: 9,
decrease: () => {
console.log(this) //window,window
this.num--
},
}
a.decrease()
a.decrease()
console.log(a.num) //9
因为箭头函数没有自己的this,所以也就不能用call()、apply()、bind()这些方法去改变this的指向
window.num = '1'
let num = '2'
let obj = {
num: '3'
}
let sayNum = () => this.num
console.log(sayNum.call(obj)) //1
补充说明:
bind,call,apply
的异同
同:
1.第一个参数都是this要指向的对象
2.都可以利用后续参数传参
3.都是用来改变函数的this对象的指向
异:
1.call和apply都是对函数的直接调用,而bind方法返回的仍然是一个函数,所以后面还需要()来进行调用
2.call后面的参数与say方法中是一 一对应的,apply的第二个参数是一个数组,数组中的元素是和say方法中一 一对应的
9.不绑定参数(arguments)
箭头函数不会在其内部暴露(指向)出arguments参数,而是指向箭头函数所在作用域的一个名为arguments的值,若有就是undefined
虽然箭头函数没有自己的 arguments ,但在多数情形下,rest参数可以给出一个解决方案:
function fn() {
var a = (...args) => args[0];
return a(2);
}
console.log(fn()); // 2
拓展:
ES6的rest参数(…扩展符)可以获取箭头函数不定数量的参数
let a = (num1, ...nums) => {
console.log(num1, nums); // 1 [2, 3, 4]
};
a(1, 2, 3, 4);
1.箭头函数的this指向全局,使用arguments会报未声明的错误
let a = () => {
console.log(arguments);
};
a(1, 2, 3, 4); // Uncaught ReferenceError: arguments is not defined
2.箭头函数的this如果指向普通函数,它的argumens继承于该普通函数
function fn() {
console.log(arguments); // ['外层第二个普通函数的参数']
a('外层第一个普通函数的参数');
function a() {
console.log(arguments); // ["外层第一个普通函数的参数"]
let b = () => {
console.log(arguments, 'arguments继承this指向的那个普通函数'); // ["外层第一个普通函数的参数"]
};
b('箭头函数的参数'); // this指向a
}
}
fn('外层第二个普通函数的参数');
10.不支持new.target
箭头函数的this指向全局对象,在箭头函数中使用箭头函数会报错
let a = () => {
console.log(new.target); // 报错:new.target 不允许在这里使用
};
a();
箭头函数的this指向普通函数,它的new.target就是指向该普通函数的引用
new a();
function a() {
let b = () => {
console.log(new.target); // 指向函数a:function a(){...}
};
b();
}
11.不支持重命名函数参数
普通函数的函数参数支持重命名,后面出现的会覆盖前面的,箭头函数会抛出错误
function fn(a, a) {
console.log(a, arguments); // 2 [1,2]
}
fn(1, 2);
箭头函数的this指向普通函数,它的new.target就是指向该普通函数的引用
var fn = (a,a) => {
console.log(a); // 报错:在此上下文中不允许重复参数名称
};
fn(1, 2);