有了对call()、apply()的前提分析,相信bind()我们也可以手到擒来。

参考前两篇:'对call()函数的分析' 和 '对apply()函数的分析',我们可以先得到以下代码:

Function.prototype.myBind = function(obj){
  // 判断调用对象是否为函数
  if(typeof this !== 'function'){
    console.error('type error!')
  }
  // 判断绑定的对象
  obj = obj || window;
}

bind()函数与call()函数参数的格式相同,不同的是bind()返回的是一个函数。

Function.prototype.myBind = function(obj){
  if(typeof this !== 'function'){
    console.error('type error!')
  }
  obj = obj || window;
  // 获取正确参数
  let args = [...arguments].slice(1);
  // 返回函数
  return function Fn(){};
}

使用bind()函数来对this进行绑定,可以之间在内部使用 apply() 。

Function.prototype.myBind = function(obj){
  if(typeof this !== 'function'){
    console.error('type error!')
  }
  obj = obj || window;
  let args = [...arguments].slice(1);
  return function Fn(){
    // 直接使用apply()
    return this.apply();
};
}

这个时候会发现,我们绑定的this是window,而不是我们想要的’this‘环境,可以使用that作为中间量。

Function.prototype.myBind = function(obj){
  if(typeof this !== 'function'){
    console.error('type error!')
  }
  obj = obj || window;
  // 在这里借助that
  that = this;
  let args = [...arguments].slice(1);
  return function Fn(){
    return that.apply();
};
}

然后我们需要考虑apply()中传递的参数,这里我们使用数组的concat()方法,得到apply中传递的数组。

Function.prototype.myBind = function(obj){
  if(typeof this !== 'function'){
    console.error('type error!')
  }
  obj = obj || window;
  that = this;
  let args = [...arguments].slice(1);
  return function Fn(){
// 传递两个参数(绑定对象,数组)
    return that.apply(obj,args.concat(...arguments));
};
}

最后需要判断函数作为构造函数的情况,这个时候需要传入当前函数的 this 给 apply 调用,其余情况都传入指定的上下文对象。

Function.prototype.myBind = function(obj){
  if(typeof this !== 'function'){
    console.error('type error!')
  }
  obj = obj || window;
  that = this;
  let args = [...arguments].slice(1);
  return function Fn(){
// 根据调用方式,传入不同绑定值
    return that.apply(
      this instanceof Fn ? this : obj,
      args.concat(...arguments));
};
}

最后通过一个例子,来验证是否达到bind()的功能要求。

Function.prototype.myBind = function(obj){
  if(typeof this !== 'function'){
    console.error('type error!')
  }
  obj = obj || window;
  that = this;
  let args = [...arguments].slice(1);
  return function Fn(){
    return that.apply(
      this instanceof Fn ? this : obj,
      args.concat(...arguments)
    );
  }
}
let dog = {
  name: '狗',
  eat(food1, food2) {
    console.log(this.name + '爱吃' + food1 + food2);
  }
}
let cat = {
  name: '猫',
}
dog.eat.bind(cat, '鱼', '肉')(); // 猫爱吃鱼肉
dog.eat.mybind(cat, '鱼', '肉')(); // 猫爱吃鱼肉

理解并手写 bind() 函数的更多相关文章

  1. 理解并手写 call() 函数

    手写自己的call,我们要先通过call的使用,了解都需要完成些什么功能? call()进行了调用,是个方法,已知是建立在原型上的,使用了多个参数(绑定的对象+传递的参数). 我们把手写的函数起名为m ...

  2. 手写bind函数

    实现bind函数 参考MDN提供的Polyfill方案 Function.prototype.myBind = function(context){ //这里对调用者做一个判断,如果不是函数类型,直接 ...

  3. 理解并手写 apply() 函数

    apply()函数,在功能上类似于call(),只是传递参数的格式有所不同. dog.eat.call(cat, '鱼', '肉'); dog.eat.apply(cat, ['鱼', '肉']); ...

  4. 前端面试题整理——手写bind函数

    var arr = [1,2,3,4,5] console.log(arr.slice(1,4)) console.log(arr) Function.prototype.bind1 = functi ...

  5. WPF启动流程-自己手写Main函数

    WPF一般默认提供一个MainWindow窗体,并在App.Xaml中使用StartupUri标记启动该窗体.以下通过手写实现WPF的启动. 首先先介绍一下VS默认提供的App.Xaml的结构,如下图 ...

  6. 优雅手撕bind函数(面试官常问)

    优雅手撕bind函数 前言: 为什么面试官总爱让实现一个bind函数? 他想从bind中知道些什么? 一个小小的bind里面内有玄机? 今天来刨析一下实现一个bind要懂多少相关知识点,也方便我们将零 ...

  7. python 精华梳理(已理解并手写)--全是干货--已结

    基础部分 map,reduce,filter,sort,推导式,匿名函数lambda , 协程,异步io,上下文管理 自定义字符串转数字方法一不使用reduce import re def str2i ...

  8. C++之手写strlen函数

    代码: int strlen(const char *str){ assert(str!=NULL); intlen=; while((*str++)!='\0') len++; return len ...

  9. js面试题之手写节流函数和防抖函数

    函数节流:不断触发一个函数后,执行第一次,只有大于设定的执行周期后才会执行第二次 /* 节流函数:fn:要被节流的函数,delay:规定的时间 */ function throttle(fn,dela ...

随机推荐

  1. Git 保存和恢复工作进度(stash)

    感谢原文作者:滑稽的命运 原文链接:https://www.jianshu.com/p/1e65e938f93c 作用: 封存工作区与暂存区已经被Git版本控制,但没有提交(Commit)版本库的文件 ...

  2. Nodejs基于Express使用html模板

    express默认使用jade模板,可以配置让其支持使用ejs或html模板. 安装ejs 在项目根目录安装ejs. npm install ejs 2.引入ejs var ejs = require ...

  3. 3、架构--cp、scp、rsync、实时监控与同步

    笔记 1.晨考 1.VPN的搭建步骤 2.vpn中的iptables是什么作用? 网络转发 2.昨日问题 1.yum源问题 2.VPN链接正常,但是没办法通过172 3.VPN链接时,出现了DNS错误 ...

  4. Keras学习:第一个例子-训练MNIST数据集

    import numpy as npimport gzip import struct import keras as ks import logging from keras.layers impo ...

  5. Solution -「NOI.AC 省选膜你赛」union

    题目 题意简述   给定两颗树 \(A,B\),\(A\) 中的任一结点 \(u\) 与 \(B\) 中的任一结点 \(v\) 都有一个关系值 \(f(u,v)\),初始为 \(0\).再给出 \(q ...

  6. Solution -「集训队作业 2013」「洛谷 P4841」城市规划

    \(\mathcal{Description}\)   link.   求 \(n\) 个结点的简单无向连通图个数,对 \(1004535809~(479\times2^{21}+1)\) 取模.   ...

  7. Solution -「LOCAL」人口迁徙

    \(\mathcal{Description}\)   \(n\) 个点,第 \(i\) 个点能走向第 \(d_i\) 个点,但从一个点出发至多走 \(k\) 步.对于每个点,求有多少点能够走到它. ...

  8. 多个UID为0的用户如何实现root用户的免密

    文章目录 创建用户 创建用户密码 免密脚本 当前主机用户不是root 当前主机用户是root,远程主机多个用户uid为0 利用shell脚本实现远程主机uid为0的用户只有root一个 多个UID=0 ...

  9. 通过JAVA对FTP服务器连接,上传,下载,读取,移动文件等

    记录一次对FTP服务器文件内容 通过Java程序对FTP服务器文件处理:连接,上传,下载,读取,移动文件等. 需求描述:今天接到一个任务,在Java项目中,读取FTP服务器上的一些文件,进行一些业务操 ...

  10. html页面预览pdf文件使用插件pdfh5.js

    html预览pdf文件需要依赖pdf.js 移动端适配需要pdfh5.js 记录移动端适配pdfh5.js的用发 在线预览: https://www.gjtool.cn/pdfh5/pdf.html? ...