精华内容
下载资源
问答
  • 如何自己实现bind方法

    2019-06-20 05:51:23
    由于在低版本浏览器没有js原生bind方法,所以要兼容低版本浏览器的话就要手动实现 了解bind函数 bind 强制将函数的执行环境绑定到目标作用域中去 与 call 和 apply 其实有点类似,但是不同点在于,bind 方法不会立即...

    由于在低版本浏览器没有js原生bind方法,所以要兼容低版本浏览器的话就要手动实现

    了解bind函数

    bind 强制将函数的执行环境绑定到目标作用域中去

    与 call 和 apply 其实有点类似,但是不同点在于,bind 方法不会立即执行,而是返回一个改变了上下文 this 后的函数

    因此我们要想自己实现一个 bind 函数,就必须要返回一个函数,而且这个函数会接收绑定的参数的上下文。

    if (!Function.prototype.bind) {
        Function.prototype.bind = function () {
            if(typeof this != 'function'){// 判断调用者是不是函数
                throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
            }
            var self = this,                        // 保存原函数 (this指向调用bind者)
            context = [].shift.call(arguments), // 把参数中的第一个剪切出来,保存需要绑定的this上下文
            args = [].slice.call(arguments);    // 剩余的参数转为数组
            return function () {                    // 返回一个新函数
                self.apply(context,[].concat.call(args, [].slice.call(arguments)));
            }
        }
    }
    复制代码

    arguments 的含义

    arguments 是一个对应于传递给函数的参数的类数组对象,没有 shift 等数组独有的方法

    function fun(){
      console.log(arguments)
      console.log(Array.prototype.slice.call(arguments))
    }
    console.log(fun('a','b'));
    复制代码

    arguments转换成数组 方法一

    先将 arguments 转为数组,然后再对其运用了 slice 方法 Array.prototype.shift === [].shift

    Array.prototype.slice.call(arguments); //通过原型的方式直接在类上调用
    [].slice.call(arguments);    //通过实例化,继承过来,然后再调用
    
    //["a", "b"]
    复制代码

    arguments转换成数组 方法二

    es6 为数组新增了一个 from 方法

    Array.from(temp).slice();   //["a", "b"]
    复制代码

    为什么要合并参数

    作者看文章的时候看到[].concat.call(args, [].slice.call(arguments)也有点蒙圈,参数不就是args么,为什么要合并它自己?如果你也是这么认为的那就请认真往下阅读 其实args是绑定上下文的时候(也就是bind())传递的参数,而后面的arguments则是调用bind()()第二个括号传递的参数,所以这里才会需要合并 如果还是有点不明白可以看看一下的代码,懂了的可跳过啦

    Function.prototype.binding = function () {
        let self = this;
        let context = [].shift.call(arguments);
        let args = [].slice.call(arguments);
        console.log(args);
    
        return function () {
            self.apply(context, [].concat.call(args, [].slice.call(arguments)))
        }
    };
    
    let obj = {
        a: 'a'
    };
    
    function f(b, c, d) {
        console.log(this.a, b, c, d)
    }
    
    f.binding(obj, 'b', 'c', 'd')('e');
    f.binding(obj, 'b', 'c')('d', 'e');
    f.binding(obj, 'b')('c', 'd', 'e');
    f.binding(obj)('b', 'c', 'd', 'e');
    
    输出:
    [ 'b', 'c', 'd' ]   a b c d
    [ 'b', 'c' ]   a b c d
    [ 'b' ]   a b c d
    [] a b c d
    复制代码

    补充

    slice() 方法可从已有的数组中返回选定的元素  //slice(2,4)
    shift() 方法用于把数组的第一个元素从其中删除,并返回第一个元素的值
    unshift() 方法可向数组的开头添加一个或更多元素,并返回新的长度
    复制代码
    Array.from() 
    从一个类似数组或可迭代对象中创建一个新的,浅拷贝的数组实例。
    
    Array.from('foo'); //Array ["f", "o", "o"]
    Array.from([1, 2, 3], x => x + x); //Array [2, 4, 6]
    复制代码

    apply的用法

    function setName(){
      this.name='haha';
    }
    function person(){
      setName.apply(this);
    }
    var person=new person();
    console.log(person.name);
    复制代码

    apply与bind的区别

    const person = { name: 'ximelly' }
    
    function sayHi(age) {
    console.log(`${this.name} is ${age}`)
    }
    
    //call和apply 立即执行
    sayHi.call(person, 21)
    
    //bind 返回带有绑定上下文的函数副本,但不立即执行
    sayHi.bind(person, 21)()
    sayHi.bind(person)(21)
    复制代码

    转载于:https://juejin.im/post/5d0b1903f265da1b904be75e

    展开全文
  • bind()方法: 会创建一个新函数。当这个新函数被调用时,bind() 的第一个参数将作为它运行时的 this,之后的一序列参数将会在传递的实参前传入作为它的参数。(来自于 MDN ) 此外,bind实现需要考虑实例化后对...

    bind()方法:

    会创建一个新函数。当这个新函数被调用时,bind() 的第一个参数将作为它运行时的 this,之后的一序列参数将会在传递的实参前传入作为它的参数。(来自于 MDN )

     

     此外, bind实现需要考虑实例化后对原型链的影响。

     

    Function.prototype.mybind = function (context) {
      if (typeof this !== "function") {
          throw new Error(this + "is not a function");
      }
      var self = this;
      var args = [];
      for (var i = 1, len = arguments.length; i < len; i++) {
          args.push(arguments[i]);
      }
    
      var fbound = function () {
          var bindArgs = Array.prototype.slice.call(arguments);
          self.apply(this instanceof self ? this : context, args.concat(bindArgs));
      }
      fbound.prototype = Object.create(self.prototype);
      //返回的函数不仅要和 被调函数的函数体相同,也要继承人家的原型链
      return fbound;
    }

     

    展开全文
  • 主要给大家介绍了关于如何手动实现es5中的bind方法的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面小编来一起学习学习吧
  • 很久前写过一篇call,apply,bind的作用,最近学习的过程中看了一篇手写这三个方法的文章。才想起这么多年其实一直知其然不知所以然,还是要更深入原理才好,接下来整理一下我自己的写法。 实现call 首先我们看call...

    很久前写过一篇call,apply,bind的作用,最近学习的过程中看了一篇手写这三个方法的文章。才想起这么多年其实一直知其然不知所以然,还是要更深入原理才好,接下来整理一下我自己的写法。

    实现call

    首先我们看call的用法,比如fn.call(obj,a,b,...)。从中可以看书,call是函数的一个方法,所以我们把它加在Function.prototype上,传入上下文context,首先判断this是否是function,不是就提示错误。另外当context不传时默认为window。然后再处理传入的参数即可,代码如下:

    Function.prototype.myCall = (context = window, ...args) {
    	if(typeOf this !== 'function') {
    		throw new TypeError('Error');
    	}
    	// 我们需要暂时将this挂载在context上
    	// 为了确保不因为属性名冲突而污染context对象
    	// 我们使用Symble来获取独一无二的值fn
    	const fn = Symble('fn');
    	// 然后挂载
    	context[fn] = this;
    	const result = context.fn(...args);
    	// 执行完删掉fn,保证context跟原来一样
    	delete context[fn];
    	// 返回结果
      	return result;
    }
    

    实现apply

    实现了call方法之后,apply方法就很简单了,他俩的区别只在于参数而已,代码如下:

    Function.prototype.myApply = (context = window, args) {
    	if(typeOf this !== 'function') {
    		throw new TypeError('Error');
    	}
    	const fn = Symble('fn');
    	context[fn] = this;
    	let result = args ? context.fn(...args) : context.fn();
    	delete context[fn];
      	return result;
    }
    

    实现bind

    bind和之前两者的区别在于,他不会立即执行,只是绑定了上下文

    • 前几步和之前的实现大相径庭,就不赘述了
    • bind 返回了一个函数,对于函数来说有两种方式调用,一种是直接调用,一种是通过 new 的方式,我们先来说直接调用的方式
    • 对于直接调用来说,这里选择了 apply 的方式实现,但是对于参数需要注意以下情况:因为 bind 可以实现类似这样的代码f.bind(obj, 1)(2),所以我们需要将两边的参数拼接起来,于是就有了这样的实现args.concat(...arguments)
    • 最后来说通过 new 的方式,在之前的章节中我们学习过如何判断 this,对于 new 的情况来说,不会被任何方式改变 this,所以对于这种情况我们需要忽略传入的 this

    所以代码如下:

    Function.prototype.myBind = (context, ...args) {
    	if(typeOf this !== 'function') {
    		throw new TypeError('Error');
    	}
    	const fn = this
      	return function F() {
    		// 因为返回了一个函数,我们可以 new F(),所以需要判断
    	    if (this instanceof F) {
    	    	// F在this的原型链上,所以是new出来的
    	    	// new 出来的新函数,他的this定在new的时候,此时忽略这个context
    	    	return new fn(...args, ...arguments);
    	    }
    	    // 正常调用bind的时候,再给他apply返回
    	    return fn.apply(context, args.concat(...arguments));
    	}
    }
    
    展开全文
  • 原生实现bind()方法

    2019-11-10 14:06:34
    正常情况下bind()是如何使用的?? Math.max.bind([],3,2,1,34,23,55,4) .bind(obj,参数1,参数2…) 因为形参只设了一个obj,所以obj为第一个实参,所有实参都在arguments里 Function.prototype.mybind = function ...
    • 正常情况下bind()是如何使用的??
      Math.max.bind([],3,2,1,34,23,55,4)
      .bind(obj,参数1,参数2…)
      因为形参只设了一个obj,所以obj为第一个实参,所有实参都在arguments里
    Function.prototype.mybind = function (obj) {
        // 截取参数1,参数2...
        // [3,2,1,34,23,55,4].slice(2,4) // 结果为:[1,34]
        // [3,2,1,34,23,55,4].slice(1) // 结果为:[2, 1, 34, 23, 55, 4]
        var myarguments = [].slice.call(arguments, 1)
        // 返回Math.max运行结果,this指向任意函数
        return this.apply(obj, myarguments)
    }
    var res = Math.max.mybind([], 9, 10, 400, 66)
    console.log(res);//400
    
    展开全文
  • call、apply 和 bind本质上都是要改变 this 的指向,在实现过程中一定要时刻搞清楚 this 的...如果不用call、apply 和bind如何让 show 方法里的 this 指向 person 对象呢? 可以像下面这样做 const person = { nam
  • 自从进入七月以来,我的 underscore 源码解读系列 更新缓慢,再这样下去,今年更完的目标似乎要落空,赶紧写一篇压压惊。...今天就根据 underscore 的实现,来聊一聊如何实现一个 bind 的 polyfill。 之前在 ECMAScr...
  • 方法:都是改变函数体内部this的指向,可实现构造函数的继承1.bind()2.call()3.apply()例1:区别例2:bind()改变this指向,实现继承例3:综合改变this指向实现继承的优缺点 1.bind() 第一个参数:this指向 ...
  • apply方法bind方法 模拟实现 Function.prototype._bind = function(target) { // 保留调用_bind方法的对象 let _this = this; // 接收保存传入_bind方法中的参数,等价于arguments.slice(1),除了第一个参数其余...
  • 如何手动实现这三个方法呢?且往下看: 1、bind、call、apply的区别是什么? bind被称为是绑定函数,其函数内部的this指向创建它时传入bind的第一个参数,而传入bind的第二个以及后面的参数则作为原来函数的参数...
  • 前一篇文章我们尝试模拟实现了 call 和 apply 方法,其实 bind 函数也可以用来改变 this 的指向。bind 和 call和 apply 两者的区别在于,bind 会返回一个被改变了 this 指向的函数。 本文介绍如何模拟实现 bind 函数...
  • 我们都知道对于 this ...要想直接当全局的方法来使用,那么需要在 Function 原型上添加bind方法; 获取方法自身的 this 指向 获取调用函数的上下文(传递参数) 通过 apply 改变其指向并返回 Function.prototype....
  • Call,Apply,Bind的使用与区别 ,如何实现一个bind?Call,Apply,Bind的使用与区别实现一个bind Call,Apply,Bind的使用与区别 相同点: 都是使用与方法借用以及明确this指向场景 第一个参数都是this要指向的...
  • 问题: 在AngularJS 1.x 中可以使用ng-bind-html来插入一段html代码,相当于struts2 标签的escape属性。...解决方法: 使用[innerHtml]代替ng-bind-html。 innerHtml属性,用于设置标签内的h
  • Call,Apply,Bind的使用与区别,如何实现一个bind? 相同点: 都是使用于方法借用及明确this指向场景 第一个参数都是this要指向的对象 都可以利用后续参数传参 不同点: 参数传递方式不同 call,apply是立即调用,...
  • call, apply, bind这三个方法都可以改变函数内部this指向。区别是call, apply是立即指向该函数,而bind是返回一个新的函数,用于下次调用。 其中,call和apply的区别是传递函数参数的方式不同,call是一个一个传入,...
  • 写在前面call、apply和bind是强制改变this指向的几种方法。大家应该看过了很多关于手写call、apply和bind的文章,并且自己手动尝试,已经实现手写源码~所以我写这篇文...
  • 实现一个Bind和New

    2019-03-28 02:06:30
    通过给目标函数指定作用域来简单实现bind()方法 Function.prototype.bind = function(context){ self = this; return function(){ return self.apply(context,arguments); } } 复制代码考虑到函数科里化的情况 ...
  • 使用文本配置文件的配置方式结合bind的最新的acl和view特性来实现智能DNS想必很多人已经很熟悉了,使用MySQL数据库来存放zone文件的方式可能也不少。对于两者都熟悉的,实现 Bind+DLZ+MySQL正向解析的也已经很多了,...
  • 继承进阶:如何实现new、apply、call、bind的底层逻辑 思考问题: 1、用什么样的思路可以new关键词? 2、apply、call、bind这三个方法之间有什么区别? 3、怎样实现一个apply或者call的方法? new原理介绍 new...
  • 在一次项目开发中,需要将类内的一些非static成员方法... 但这样做比较别扭,额外写不少不少代码,而boost的function和bind恰恰解决了这个问题。 可能不少人有疑惑,类的非static成员函数为啥就比较

空空如也

空空如也

1 2 3 4 5 ... 17
收藏数 332
精华内容 132
关键字:

如何实现bind方法