【前端手撕】call call是改变this指向的方法传入的参数是要指向的对象和函数需要的参数序列。改变this指向还可以用apply和bind区别如下方法传参方式执行时机返回值call参数序列逐个传入立即执行函数执行的结果apply参数数组或类数组立即执行函数执行的结果bind参数序列逐个传入返回新函数稍后执行绑定了this的新函数代码简易版Function.prototype.callSimple function (context, ...args) { context context || window // 确认上下文如果没有上下文就默认window context.fn this // 把当前函数赋值给上下文的fn属性临时属性 const res context.fn(...args) // 调用函数传参 delete context.fn // 删除临时属性 return res }健壮版Function.prototype.call function (context, ...args) { // 如果上下文是null或undefined就默认window否则用Object()转换为对象 // Object()包对象返回原对象包原始类型返回对象包装类型。这是因为简单数据类型不能挂载属性对象才可以 context context ! null context ! undefined ? Object(context) : window let tag Symbol(call) // Symbol()创建一个唯一的符号值避免与其他属性冲突/覆盖 context[tag] this // 把当前函数赋值给上下文的tag属性临时属性 const res context[tag](...args) // 调用函数传参。这里使用方括号是因为tag是一个符号值不能用点号 return res }Tips1. bind传参数可以先传一部分参数返回新函数下次再传剩下的。这种特性叫函数柯里化Currying2. 如果bind返回的新函数被new构造调用了this会失效。因为new的优先级高于bind但也只有new比bind高function Person(name) { this.name name; } const BoundPerson Person.bind({ name: 默认 }); // 试图绑定 this const p new BoundPerson(李四); console.log(p.name); // 输出李四因为new强行创建了一个新对象作为thisbind绑定的this被覆盖了。