this、箭头函数、call / apply / bind 有什么区别
先理解原理和示例,再练习完整口述与追问。
回答要点
普通函数的 this 与调用方式有关;箭头函数使用外层词法 this。call / apply 立即调用,bind 返回绑定后的函数。准备解释方法被单独取出、回调传递、new 调用时的差异。
原理拆解
普通函数的 this 主要由调用方式决定:obj.fn() 以 obj 为接收者,独立调用在严格模式中为 undefined,call/apply 显式指定接收者,new 创建实例并以实例调用构造过程。bind 返回保存接收者和前置参数的新函数。箭头函数则从外层词法环境取得 this,自身没有可被 call、apply、bind 改写的 this,也不能作为构造函数。
示例与推演
'use strict'
const obj = { n: 2, read() { return this.n } }
const read = obj.read
console.log(read.call({ n: 7 })) // 7
console.log(obj.read.bind({ n: 9 })()) // 9
// read() 会因 this 是 undefined 而报错
call(fnThis,a,b) 与 apply(fnThis,[a,b]) 的差别在传参形式;bind 不会立即执行原函数。
易错点
不要按“在哪里定义就指向谁”解释普通函数。对象方法写成箭头函数,也不会自动把 this 绑定到那个对象;回调是否丢失 this,应看实际调用表达式。
参考回答可直接练习口述
普通函数的 this 主要由调用方式决定:作为 obj.method() 调用指向 obj,显式 call/apply 可指定,new 调用会建立新实例;独立调用在严格模式中通常为 undefined。箭头函数没有自己的 this,使用外层词法 this,不能靠 call/bind 改成新的 this,也不能作为普通构造器。call 逐个传参,apply 接收参数列表,bind 返回一个绑定调用方式的新函数,调用时机与前两者不同。