js中自己实现bind方法及详解

  1. 详细代码如下:
if (!Function.prototype.bind) {
    Function.prototype.bind = function () {
        var self = this,                        // 保存原函数
        context = [].shift.call(arguments), // 保存需要绑定的this上下文
        args = [].slice.call(arguments);    // 剩余的参数转为数组
        return function () {                    // 返回一个新函数
            self.apply(context,[].concat.call(args, [].slice.call(arguments)));
        }
    }
}
  1. 详解代码
    2.1 bind的简单理解
        bind是用来绑定上下文的,强制将函数的执行环境绑定到目标作用域中去。与call和apply类似,但不同点在于,他不会立即执行,而是返回一个函数。因此想要自己实现一个bind函数,就必须要返回一个函数,让这个函数接受绑定的参数的上下文。
    2.2 arguments
    (1)定义:arguments是一个对应于传递给函数的参数类数组对象
    (2)实质是对象,typeof arguments 的结果是object。arguments对象只能在函数内部使用
    (3)不是数组,类似于数组,除了length属性和索引元素之外没有任何Array属性。但是可以被转换为一个真正的数组,下图是转化为数组的4种方法
    js中自己实现bind方法及详解
    (4) 实例
    js中自己实现bind方法及详解
    2.3 [].shift.call(arguments)
    (1)[].shift
      其实 Array.prototype.shift === [].shift,两者其实是同一个函数,只是调用的方式存在差异,一个是通过原型的方式直接在类上调用;一个是通过实例化,继承过来,然后再调用。
    (2) call
      call() 方法调用一个函数, 其具有一个指定的this值和分别地提供的参数(参数的列表)。
    (3)综上:[].shift.call(arguments)这条语句的含义是将arguments转化为数组,再对其运用shift方法,得到传入的参数中的第一个参数即this
    2.4 返回函数
return function () {    // 返回一个新函数
    self.apply(context,[].concat.call(args, [].slice.call(arguments)));
}

(1)apply函数接受两个参数(第一个参数是this上下文,第二个参数是数组列表)
(2)合并参数
① 将bind 的其余参数和调用bind后返回的函数在执行的过程中接收的参数进行拼接,作为一个数组传入apply的第二个参数中去。
② args是绑定上下文的时候(也就是bind())传递的参数,而后面的arguments则是调用bind()()第二个括号传递的参数,所以这里才会需要合并
(3)如果对于合并参数还是不太明白,可以看下下面的代码

//my_bind方法不仅可以绑定对象,还可以传参
Function.prototype.my_bind = function(context){
	var args = Array.prototype.slice.call(arguments, 1);
	//args [7, 8]
	var self = this;
	return function(){
		var innerArgs = Array.prototype.slice.call(arguments);
		//innerArgs [9]
		var finalArgs = args.concat(innerArgs);
		//finalArgs [7, 8, 9]
		return self.apply(context, finalArgs);
	}
}
 
//测试
function a(m, n, o){
	return this.name + ' ' + m + ' ' + n + ' ' + o;
}
var b = {name : 'kong'};
a.my_bind(b, 7, 8)(9);		//kong 7 8 9

本文参考了博文https://blog.csdn.net/lovefengruoqing/article/details/80186401,若有兴趣的小伙伴可以看看原文章。

上一篇:Xcode中的变量模板(variable template)的用法


下一篇:ES6箭头函数与this指向