JavaScript系列—手写bind()函数

本人在一次面试中,当面试官小姐姐让我重写一下bind函数的时候,一下子蒙圈了,所以特来研究一下。

在手写bind函数之前,我们先来回顾一下三剑客

1.call,apply和bind

现在我们写一个例子看一下

打印 

特殊的,假如this那块写了一个1,那么打印出来的就不是1,而是被包装成一个对象

 

2.手写bind实现

首先看一下下面的代码

猜测一下这个this指向的是谁,这也是一道面试题。指向的是func函数,其实很简单,谁调用它它就指向谁,so不要和原型链搞混了,两码事!

 下来我们开始实现

<!DOCTYPE <!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>Page Title</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
  </style>
  <script>
    Function.prototype.customeBind = function(thisArg,...list){
      let self = this; // 目标函数
      console.log('customeBind----this----------')
      console.log(this);  //指向func
      console.log('customeBind----this----------')

      return function(...arg2){
        self.apply(thisArg,[...list,...arg2])
      }
    }

    function func(...arg){
      console.log('答案是我,我是func');
      console.log(this);//this已经改变,指向{a:1}
      console.log(arg);//{1,2,3,4,5,6,7,8}
      console.log('答案是我,我是func');
    }

    // let newFunc = func.bind(1,2,3);
    // newFunc(5, 6, 7, 8);
    let newFunc2 = func.customeBind({a:1},1,2,3,4);
    newFunc2(5,6,7,8);
  </Script>
</head>
<body class="Site">

<div class="parent">

</div>
</body>
</html>

 下来我们看一下原生的bind

3. 使用构造函数new

我们现在使用构造函数

<!DOCTYPE <!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>Page Title</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
  </style>
  <script>
    Function.prototype.customeBind = function(thisArg,...list){
      let self = this; // 目标函数

      return function(...arg2){
        self.apply(thisArg,[...list,...arg2])
      }
    }

    function func(...arg){
      console.log('答案是我,我是func');
      console.log(this);//this已经改变,指向{a:1}
      console.log(arg);//{1,2,3,4,5,6,7,8}
      console.log('答案是我,我是func');
    }

    func.prototype.miaov = function(){
      console.log(this);
    }


    let newFunc = func.bind({ a: 1 }, 1, 2, 3);
    let newFunc2 = func.customeBind({ a: 1 }, 1, 2, 3, 4);
    console.log('原生------------------');
    let f1 = new newFunc(5, 6, 7, 8);
    console.log(f1);
    console.log('自定义-----------------');
    let f2 = new newFunc2(5, 6, 7, 8);
    console.log(f2);
  </Script>
</head>
<body class="Site">

<div class="parent">

</div>
</body>
</html>

 继续我们寻找一下miaov这个函数

 

自定义的找不到啦 

这是因为

自己实现的bind函数,如果把返回的新函数当成了构造函数,此时会遇到问题,就是找不到目标函数原型上的方法

我们画图来说明一下吧

上面的图画的对不对,我们就来看以下代码打印一下就知道

  <script>

    function func(...arg){
      console.log('答案是我,我是func');
      console.log(this);//this已经改变,指向{a:1}
      console.log(arg);//{1,2,3,4,5,6,7,8}
      console.log('答案是我,我是func');
    }

    func.prototype.miaov = function(){
      console.log(this);
    }


    let newFunc = func.bind({ a: 1 }, 1, 2, 3);
    let f1 = new newFunc(5, 6, 7, 8);
    console.log(f1.miaov);
    console.log('看看f1----------------------');
    console.log(f1);
  </Script>

 

 

然后我们进行改正这个情况

<!DOCTYPE <!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>Page Title</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
  </style>
  <script>
    Function.prototype.customeBind = function(thisArg,...list){
      let self = this; // 目标函数
      
      // 自己实现的bind函数,如果把返回的新函数当成了构造函数,此时会遇到问题,
      // 就是找不到目标函数原型上的方法
      // 解决:让新函数继承目标函数的原型
      let Bound = function(...arg2){
        self.apply(thisArg,[...list,...arg2])
      }
      // 以某个对象作为原型创建一个新的对象出来
      Bound.prototype = Object.create(self.prototype);
      Bound.prototype.custructor = self;

      return Bound;
    }

    function func(...arg){
      console.log('答案是我,我是func');
      console.log(this);//this已经改变,指向{a:1}
      console.log(arg);//{1,2,3,4,5,6,7,8}
      console.log('答案是我,我是func');
    }

    func.prototype.miaov = function(){
      console.log(this);
    }


    let newFunc = func.bind({ a: 1 }, 1, 2, 3);
    let newFunc2 = func.customeBind({ a: 1 }, 1, 2, 3, 4);
    console.log('原生------------------');
    let f1 = new newFunc(5, 6, 7, 8);
    console.log(f1.miaov);
    console.log('自定义-----------------');
    let f2 = new newFunc2(5, 6, 7, 8);
    console.log(f2.miaov);
    console.log('看看f2');
    console.log(f2);
  </Script>
</head>
<body class="Site">

<div class="parent">

</div>
</body>
</html>

 

哦,千呐,这么一个小小的面试题,其实涉及的知识点并不少,脑壳疼。 

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值