必备知识点:js 【详解】函数中的 this 指向_js function this-CSDN博客
https://blog.csdn.net/weixin_41192489/article/details/123093256
bind、call、apply 的相同点
- 都是Function原型上的方法
- 用途都是改变 this 的指向
- 第一个参数都是新的 this
bind、call、apply 的不同点
- bind 会返回一个新的函数,目标函数在新函数调用时才会执行
let newFunc = obj.myFn.bind(newObj,'北京','上海'); newFunc();
- call 的传参方式与bind相同(第2-N个参数用
,
分隔),但目标函数会立即执行
obj.myFn.call(newObj,'北京','上海')
- apply 只有两个参数,第一个参数是新的 this,第二个参数是由目标函数的传参构成的数组
obj.myFn.apply(newObj,['北京','上海'])
使用范例
var name="张三",age=18; var obj = { name:"李四", oldAge:this.age, myFn:function(a, b){ console.log( this.name+"年龄"+this.age,"来自"+a+"去往"+b ) } } var newObj = { name:"王五", age:22 } obj.myFn.call(newObj,'北京','上海'); // 王五年龄22 来自北京去往上海 obj.myFn.apply(newObj,['北京','上海']); // 王五年龄22 来自北京去往上海 obj.myFn.bind(newObj,['北京','上海'])(); //王五年龄22 来自北京,上海去往undefined obj.myFn.bind(newObj,'北京','上海')(); // 王五年龄22 来自北京去往上海
手写 bind
// 手写 bind Function.prototype.my_bind = function () { // 将参数拆解为数组 const argList = Array.prototype.slice.call(arguments); // 获取参数的第一项,并将参数的第一项从参数数组中移除 const first_arg = argList.shift(); // 返回一个函数 return () => { // 箭头函数中的this继承函数外的this return this.apply(first_arg, argList); }; };
还可以参考下文的手写 apply 进行更深度的改写(不使用apply)
手写 call
// 手写 call Function.prototype.my_call = function () { // 将参数拆解为数组 const argList = Array.prototype.slice.call(arguments); // 获取参数的第一项,并将参数的第一项从参数数组中移除 const first_arg = argList.shift(); // 返回函数执行的结果 return this.apply(first_arg, argList); };
还可以参考下文的手写 apply 进行更深度的改写(不使用apply)
手写 apply
// 手写 apply Function.prototype.my_apply = function (new_this, argArray) { if (new_this !== null && new_this !== undefined) { // 第一个参数不是 null 和 undefined 时,将其转换为对象 new_this = Object(new_this); } else { // 第一个参数是 null 或 undefined 时,将其重置为 window new_this = window; } // 若第二个参数没有传 argArray ,则重置为空数组 argArray = argArray || []; // 使用 Symbol 生成一个唯一的属性,避免覆盖 new_this 中的已有属性 const key = Symbol("fn"); // 将原this(即原函数)变为新this(即传入的new_this) 的方法 new_this[key] = this; // 将原函数作为新this的对象方法执行,实现函数内 this 的指向变为 新this const result = new_this[key](...argArray); // 移除新增的方法 delete new_this[key]; // 返回函数执行的结果 return result; };