call、apply、bind的实现

call,apply,bind的特点

  1. 都会改变函数指向;
  2. call 与apply的都会立即执行,区别是第一个以后的传参形式不同,call是多个单一的参数,如:xxx.call(this, arg1, arg2, arg3, ...) , apply是数组,如:xxx.apply(this, [arg1, arg2, arg3, ...]),bind 和apply类似,但是执行后会return一个新的函数,如:const fn = xxx.bind(this, arg) , 然后可以调用fn(arg2)
  3. 要让所有的函数都能调用call, apply, bind,所以我们需要将call定义到函数原型(Function.ptototype)上;

定义一个对象

const person = {
   name: "person",
   genName: function () {
     console.log("this is ", this);
     console.log("arguments is ", [...arguments]);
   },
 };

手写call

 Function.prototype.call2 = function (context) {
   const cxt = context || window; // 新的作用域
   const arg = [...arguments].slice(1); // 截取第一个参数后面的函数
   const key = Symbol(); // 定义一个唯一的key
   cxt[key] = this; // this是调用call2的函数
   cxt[key](...arg); // 立即执行该函数
   delete cxt[key];
 };
 person.genName();
 person.genName.call2(null, "Franklin", "Fu");
 // this is  {name: 'person', genName: ƒ}
 // arguments is []
 // this is  Window {window: Window, self: Window, document: document, name: '', location: Location, …}
 // arguments is ['Franklin', 'Fu']

手写apply

 Function.prototype.apply2 = function (context) {
   const cxt = context || window;
   const arg = [...arguments].slice(1);
   const fnName = Symbol();
   cxt[fnName] = this;
   cxt[fnName](arg);
   delete cxt[fnName];
 };
 person.genName();
 person.genName.apply2(null, ["Franklin", "Fu"]);
 // this is  {name: 'person', genName: ƒ}
 // arguments is []
 // this is  Window {window: Window, self: Window, document: document, name: '', location: Location, …}
 // arguments is  [[Franklin Fu]]

手写bind

 Function.prototype.bind2 = function (context) {
   const cxt = context || window;
   const arg = [...arguments].slice(1);
   const self = this; // this是调用call2的函数,闭包保存
   return function () {
     // 绑定的函数可能有返回值,所以添加return
     return self.apply(cxt, arg.concat([...arguments]));
   };
 };
 const _genName = person.genName.bind2(null, "Franklin");
 person.genName();
 _genName("Fu");
 // this is  {name: 'person', genName: ƒ}
 // arguments is []
 // this is  Window {window: Window, self: Window, document: document, name: '', location: Location, …}
 // arguments is ['Franklin', 'Fu']

版权声明:本文为qq_32247819原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。