实现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. C 函数声明、函数参数

    参考连接:https://www.runoob.com/cprogramming/c-functions.html 局部变量与全局变量在内存中的储存方式 全局变量保存在内存中的全局储存区中,占用静态的 ...

  2. 链表逆序,java实现

    package com.cskaoyan.linkedlist; //反转数组 public class LinkedListDemo2 { public static Node reverse(No ...

  3. 消息服务dubbo接口性能压测性能优化案例

    最近项目中的消息服务做了运营商的改动,导致这个服务做了重新开发 压测脚本如下: 开启200线程压测: tps只有200-300之间,平均耗时在700ms左右 开启500线程压测 500并发压测,发现平 ...

  4. i春秋CTF-“百度杯”CTF比赛 九月场 XSS平台

    “百度杯“CTF比赛 九月场 ###XSS平台   看了别人的wp才知道这里需要变数组引起报错然后百度信息收集,这一步在实战中我觉得是很有作用的,get到.       这里取百度rtiny,看别人w ...

  5. Gson+GsonFormat+Postman简单粗暴解析json

    现在有时候之前的项目需要返回来修改bug看到以下这段代码 if (test != null) { JSONTokener jsonParser = new JSONTokener(test); JSO ...

  6. SparkStreming中 `transform()`算子的 的使用

    关联 DStream 和 RDD transform(func) Return a new DStream by applying a RDD-to-RDD function to every RDD ...

  7. django中嵌套的try-except

    # 因为此时为yaml模板,而且只抓取node port,所以这样处理效率快content_dict = parse_yaml(content.replace("{{", &quo ...

  8. angular 学习记录

    3章3小结 路由传参的3种方式和路由快照,订阅, @相同路由的跳转(只是参数不同),并不会触发Oninit ,因为没有重新创建component @子路由 //此种情况 是当我路由地址是 ../Hom ...

  9. SpingBoot四——前后端分离

    ◆版权声明:本文出自胖喵~的博客,转载必须注明出处. 转载请注明出处:https://www.cnblogs.com/by-dream/p/11336057.html 根据之前的教程,我们已经可以独立 ...

  10. 残差residual VS 误差 error

    https://blog.csdn.net/jmydream/article/details/8764869 In statistics and optimization, statistical e ...