资讯专栏INFORMATION COLUMN

手写call、apply、bind函数

gecko23 / 3214人阅读

摘要:函数特点可以改变我们当前函数的指向还会让当前函数执行题目自测思路解析执行传入三个参数函数内部执行传入三个参数函数内部执行

call函数

特点:

1)可以改变我们当前函数的this指向

2)还会让当前函数执行

Function.prototype.call = function (context) {
 if (typeof this !== "function") {
    throw new TypeError(`${this} is not a function`)
  }
  context = Object(context) || window;
  context.fn = this;
  let args = [];
  for (let i = 1; i < arguments.length; i++) {
    args.push("arguments["+i+"]"); 
  }
  let r = eval("context.fn("+args+")");
  delete context.fn;
  return r;
}

题目自测

function fn1() {
  console.log(this,arguments);
  console.log(1);
  
}
function fn2() {
  console.log(this,arguments);
  console.log(2);
}
fn1.call(fn2,1,2); // fn2 [1,2] 1
fn1.call.call.call.call.call(fn2,1,2); // {number:1} [2] 2

思路解析

fn1.call(fn2,1,2)

1)call执行传入fn2,1,2三个参数

2)call函数内部context = Object(fn2) = fn2

3)fn2.fn = fn1

4)args=["arguments[1]","arguments[2]"]=[1,2]

5)eval("context.fn("+args+")") = fn2.fn(1,2) = fn2.fn1(1,2)

fn1.call.call.call.call.call(fn2,1,2)

1)call执行传入fn2,1,2三个参数

2)call函数内部context = Object(fn2) = fn2

3)fn2.fn = call

4)args=["arguments[1]",arguments[2]]=[1,2]

5)eval("context.fn("+args+")") = fn2.fn(1,2) = fn2.call(1,2)

6)call执行传入1,2两个参数

7)call函数内部context = Object(1) = Number{1}

8)Number{1}.fn = fn2

9)args=["arguments[1]"]=[1]

10)eval("context.fn("+args+")") = Number{1}.fn(2) = Number{1}.fn2(2)

注:多次调用call的时候其实是call执行的时候内部又调用了一次call,总共调用两次

apply函数

特点:

1)可以改变我们当前函数的this指向

2)还会让当前函数执行

Function.prototype.apply = function (context,args) {
  if (typeof this !== "function") {
     throw new TypeError(`${this} is not a function`)
   }
   context = Object(context) || window;
   context.fn = this;
   if(!args){
    return context.fn();
   }
   let r = eval("context.fn("+args+")");
   delete context.fn;
   return r;
 }
new操作符

特点

新生成了对象

链接到原型

绑定this

返回一个对象

/*
 *基本使用 
 */
function Animal(type) {
  this.type = type ; 
}
Animal.prototype.say = function () {
  console.log("say");
}
let tiger = new Animal("tiger");
console.log(tiger);
--------------------------------------------------------
/*
 *方法实现
 */
function mockNew(){
    let Constructor = [].shift.call(arguments);
    let obj = {}; // 新生成了对象
    obj.__proto__ = Constructor.prototype; // 链接到原型
    let r = Constructor.apply(obj,arguments) // 绑定`this`
    return r instance Object ");//返回一个对象
}
let tiger = mockNew(Animal,"tiger");
console.log(tiger);
bind函数

特点

绑定this指向

返回一个绑定后的函数(高阶函数原理)

如果绑定的函数被new执行 ,当前函数的this就是当前的实例

new出来的结果可以找到原有类的原型

Function.prototype.bind = function (context) {
  if (typeof this !== "function") {
    throw new TypeError(`${this} is not a function`)
  }
  let that = this;
  let bindArgs = Array.prototype.slice.call(arguments, 1);
  function Fn() { };
  function bindFn() {
    let args = Array.prototype.slice.call(arguments);
    /*
     * 绑定`this`指向
     * 如果绑定的函数被`new`执行 ,当前函数的`this`就是当前的实例
     */
    that.apply(this instanceof bindFn ");this : context, bindArgs.concat(args)); 
  }
  /*`new`出来的结果可以找到原有类的原型*/
  Fn.prototype = that.prototype; 
  bindFn.prototype = new Fn();
  /*返回一个绑定后的函数*/
  return bindFn; 
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/6988.html

相关文章

  • 如何手写callapplybind

    摘要:可以改变,并且传入参数,立刻执行,返回函数返回值手写参数默认值并不会排除,所以重新赋值是调用的函数执行后删除新增属性可以改变,并且传入参数,与不同的是,传入的参数是数组或类数组,立刻执行,返回函数返回值手写参数默认值并不会排除,所以重新赋值 call Function.prototype.call(this, arg1, arg2, …..)可以改变this,并且传入参数,立刻执行,返...

    VEIGHTZ 评论0 收藏0
  • js函数this理解?手写applycallbind就够了

    摘要:一是什么函数的内部属性,引用的是函数据以执行的环境对象。函数做为节点事件调用时指向节点本身做为构造函数实力化方法时指向实例对象箭头函数里的普通函数,由于闭包函数是执行的,所以指向箭头函数的指向函数创建时的作用域。 一、this是什么? 函数的内部属性,this引用的是函数据以执行的环境对象。也就是说函数的this会指向调用函数的执行环境。 function a(){ retur...

    Cciradih 评论0 收藏0
  • 手写callapplybind及相关面试题解析

    摘要:我是前端我的全名是我是一个前端指向接收多个参数,第一个是返回值返回值是一个函数上下文的,不会立即执行。柯里化相关讲解请移步简版的实现就算完成了欢迎吐槽点赞 它们有什么不同?怎么用? call 接收多个参数,第一个为函数上下文也就是this,后边参数为函数本身的参数。 let obj = { name: 一个 } ...

    TwIStOy 评论0 收藏0
  • 手写JavaScript中的bind方法

    摘要:如果绑定后的函数被了,那么此时指向就发生改变。构造函数上的属性和方法,每个实例上都有。接下来声明一个函数,在该中获取了第二次传的参数,并且返回了的执行。的又等于的实例。至此,就实现了自己的方法。 之前已经实现过了call,apply和new。今天顺便把bind也实现下。首先: bind方法返回的是一个绑定this后的函数,并且该函数并没有执行,需要手动去调用。(从这一点看bind函数...

    AZmake 评论0 收藏0
  • 面试题里的那些各种手写

    摘要:最近准备初级前端面试,发现有很多手写实现什么的,例如什么手写实现,。后面以这道题为引线面试官可能会追问什么是执行上下文的判断,的区别手写一个函数实现斐波那契数列首先拷一个阮神在他教程里的一个写法。 最近准备初级前端面试,发现有很多手写实现什么的,例如什么手写实现bind,promise。手写ajax,手写一些算法。翻阅了很多书籍和博客。 这里做一个总结改进,算是对我后面大概为期一个月找...

    wh469012917 评论0 收藏0

发表评论

0条评论

gecko23

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<