把普通函数想成一张要签字盖章的正式合同:要写 function、要写 return、还得担心里面的 this 跑哪去了。箭头函数 => 就是一张"简写便签"——几行字就写完,而且便签上写的 this 永远跟着写便签时所在的位置,不会乱跑。代价是:this 自己被"锁死"了,不能当构造函数(不能 new)。
同样是"两个数相加",function 要写一整行,=> 一条语句直接连返回值都省了。
// 以前:正式合同,要写 function 和 return
let sum = function (a, b) { // 普通函数:关键字 function + 花括号
return a + b; // 算完还得自己写 return
};
// 现在:一张便签 (参数) => 结果
let sum = (a, b) => a + b; // 只有一条语句时,{} 和 return 都能省,结果自动返回
什么时候能省括号、什么时候必须写花括号?记住:一个参数省括号,一条语句省 return。
// 0 个参数:括号不能省(空括号也得留着)
let say = () => console.log("hello");
// 1 个参数:括号可以省掉,最省事
let hi = name => "hello " + name;
// 多个参数:括号必须有(不然不知道从哪开始)
let add = (a, b) => a + b;
// 多条语句:{} 和 return 都不能省
let calc = (a, b) => {
let s = a + b; // 第一条
return s * 2; // 第二条,必须手动 return
};
如果你只有一个参数却还是写了括号,程序不会报错,只是没省到;反过来,如果你写多条语句却省了花括号和 return,就会直接报错。因为便签只能写一行——多写几行就必须用花括号包起来并自己写 return。
function 的 this 看"谁调用它"——像看"这张合同是谁签的字";箭头函数 的 this 看"它写在哪一层"——像便签上自带的地址,搬到哪都不变。
let obj = { // 造一个对象,里面有个名字
name: "大喇叭", // 对象自己的名字
// function:this 看"谁调用",在 setTimeout 里 this 变成 window
say1: function () { // 普通方法
setTimeout(function () { // 套一个普通函数当定时器回调
console.log(this.name); // undefined(this 已经跑到 window 去了)
}, 100);
},
// 箭头函数:this 看"写在哪",就是外层那个 obj
say2: function () { // 外层还是普通 function(this 指 obj)
setTimeout(() => { // 里面套箭头函数
console.log(this.name); // 大喇叭(this 还指着 obj)
}, 100);
}
};
如果你在定时器、事件回调里还想用外层对象的 this,就用箭头函数;如果你想自己拿一个新的 this(比如事件里要读 e.target 对应的元素),就必须用 function。以前为了在 setTimeout 里保住 this,大家都得先写一句 var that = this 过渡——箭头函数把这个"绕弯"彻底省掉了。
便签就是便签,不能当"合同模板"去批量生产对象。
let Foo = () => {};
// new Foo; // ★ 报错:Foo is not a constructor(不能当构造函数)
let f = () => arguments;
// 箭头函数里根本没有 arguments 这个变量
// 想拿全部参数,改用 rest:(...args) => ...
如果你试图 new 一个箭头函数,浏览器会直接报错"不是构造函数"。因为箭头函数没有自己的 prototype、没有自己的 this、也没有 arguments——它就是一张纯便签,不适合当"造对象的模具",也不适合做需要动态 this 的对象方法。
① 可能在什么地方用:.map/.filter 回调、setTimeout/setInterval 里要拿外层 this、React/Vue 里传回调、简短的一行工具函数。
② 常见的问题:把箭头函数当对象方法导致 this 不符合预期;new 箭头函数直接报错;箭头函数里读 arguments 是 undefined。
③ 解决思路:要动态 this(如事件里拿 e.target)就用普通 function;要绑外层 this 就用箭头函数;拿全部参数用 (...args) =>;千万别 new 箭头函数。