实现bind函数

参考MDN提供的Polyfill方案

Function.prototype.myBind = function(context){
//这里对调用者做一个判断,如果不是函数类型,直接抛异常
if(typeof this !== 'function'){
throw '调用必须为函数'
}
//当我们调用bind函数时,我们可能传了不只一个参数
//如 fun.bind({}, arg1, arg2)
//我们需要把后面的参数拿出来
let args = Array.prototype.slice.call(arguments, 1);
let fToBind = this;
let fNOP = function(){};
let fBound = function(){
return fToBind.apply(this instanceof fNOP ? this : context, args.concat(arguments));
}
if(this.prototype){
fNOP.prototype = this.prototype;
} fBound.prototype = new fNOP(); return fBound;
}

fBound函数这里有个判断 this instanceof FNOP 这个其实是为了避免一种情况,因为bind函数返回的是一个函数,当我们把这个函数实例化(就是new fun())

根据官方文档 当返回的函数被实例化的时候,this指向会锁定指向该实例,不管我们传入的参数指定this指向。

在下面我们 返回的fBound函数时 继承一个空函数 FNOP, 当返回的函数被实例化之后,this instanceof fNOP 结果为true,从而指定this指向

function a (){}
function b (){} a.prototype = new b(); //如果我们返回的函数实例化了
let c = new a();
c instanceof b //true
//但是大多数情况我们都是
a instanceof b // false

如果这里明白了,那后面的就简单了,context 参数就是我们手动指定的this指向, 当我们绑定bind时会传递多个参数,执行的时候也会带参数,我们就需要把bind

函数除掉第一个以外的参数和我们调用方式时的参数进行拼接

function foo (){}
//示例中 args 就是指的[arg1, arg2]
//args.concat(arguments) 就是将所有的arg1,arg2...arg4的参数进行拼接
let newFoo = foo.bind({}, arg1, arg2);
newFoo(arg3, arg4);

另外 arguments 参数不要搞混淆了,上面那个获取的是bind时的参数(就是{}, arg1, arg2

下面的arguments 参数是指的调用时的 (就是 arg3, arg4)

手写bind函数的更多相关文章

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

    有了对call().apply()的前提分析,相信bind()我们也可以手到擒来. 参考前两篇:'对call()函数的分析' 和 '对apply()函数的分析',我们可以先得到以下代码: Functi ...

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

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

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

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

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

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

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

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

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

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

  7. C++之手写strlen函数

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

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

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

  9. 手写Bind

    Function.prototype.bind2 = function(context){ var self = this; var args = [].slice.call(arguments,1) ...

随机推荐

  1. background 设置文本框背景图

    background 属性的作用是给元素设置背景,它是一个复合属性,常用的子属性如下: background-color 指定元素的背景颜色. background-image 指定元素的背景图像. ...

  2. CSS样式表及选择器相关内容(二)-伪类与伪元素选择器

    伪类与伪元素选择器归纳: 一.伪类选择器(伪类以":"开头,用在选择器后,用于指明元素在某种特殊的状态下才能被选中)    1.a标签伪类选择器,其他标签类似        eg: ...

  3. maven 学习---Maven外部依赖

    现在,你也知道Maven做依赖管理使用Maven仓库的概念.但是,如果依赖是不提供任何远程存储库和中央存储库发生了什么? Maven提供为使用外部依赖的概念,应用在这样的场景. 举一个例子,让我们做以 ...

  4. dga model train and test code

    # _*_coding:UTF-8_*_ import operator import tldextract import random import pickle import os import ...

  5. 简单C语言程序

    #include<stdio.h> int main(void) { /* 计算两个时间的时间差 */ int hour1, minute1; int hour2, minute2; pr ...

  6. Nginx 初步认识

    序言 Nginx是lgor Sysoev为俄罗斯访问量第二的rambler.ru站点设计开发的.从2004年发布至今,凭借开源的力量,已经接近成熟与完善. Nginx功能丰富,可作为HTTP服务器,也 ...

  7. 201871010106-丁宣元 《面向对象程序设计(java)》第六—七周学习总结

    201871010106-丁宣元 <面向对象程序设计(java)>第六—七周学习总结 正文开头 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu- ...

  8. LiunxCentos7 上安装 FastDFS

    Centos7 上安装 FastDFS 1.安装gcc(编译时需要) FastDFS是C语言开发,安装FastDFS需要先将官网下载的源码进行编译,编译依赖gcc环境,如果没有gcc环境,需要安装gc ...

  9. TCP数据的传输过程(十)

    建立连接后,两台主机就可以相互传输数据了.如下图所示: 上图给出了主机A分2次(分2个数据包)向主机B传递200字节的过程.首先,主机A通过1个数据包发送100个字节的数据,数据包的 Seq 号设置为 ...

  10. LG4035/BZOJ1013 「JSOI2008」球形空间产生器 高斯消元

    问题描述 LG4035 BZOJ1013 题解 设答案为\((p_1,p_2,p_3,...,p_n)\) 因为是一个球体,令其半径为\(r\),则有 \[\sum_{i=1}^{n}{(a_i-p_ ...