模拟apply/call/bind

call

先看call

call() 方法在使用一个指定的 this 值和若干个指定的参数值的前提下调用某个函数或方法。

两点:

  1. call 改变了 this 的指向
  2. 执行了

实现思路, 举个例子:

	var foo = {
	    value: 1
	};
	
	function bar() {
	    console.log(this.value);
	}
	
	bar.call(foo); // 1

想想: 我们把bar函数挂载到foo下不就行了吗

	var foo = {
	    value: 1,
	    bar: function() {
	        console.log(this.value)
	    }
	};
	
	foo.bar(); // 1

ok, 仔细想想, 要求如下:

  1. 将函数设为对象的属性
  2. 若传入为null, 指向window
  3. 可能带有参数
  4. 执行该函数
  5. 可能有返回值
  6. 删除该函数

实现es5:

	Function.prototype.call = function (context) {
		// 若传入为null, 指向window
	    var context = context || window;
	    context.fn = this;
	    // 拿到参数
	    var args = [];
	    for(var i = 1, len = arguments.length; i < len; i++) {
	        args.push('arguments[' + i + ']');
	    }
		// 执行
	    var result = eval('context.fn(' + args +')');
		// 删除
	    delete context.fn
	    // 返回值
	    return result;
	}

实现es6:

	Function.prototype.call = function (context) {
		// 若传入为null, 指向window
	    var context = context || window;
	    context.fn = this;
	    // 拿到参数
	    var [a, ...args] = [...arguments];
		// 执行
	    var result = context.fn(...args);
		// 删除
	    delete context.fn
	    // 返回值
	    return result;
	}

apply

与call一致, 只是参数格式是数组而已

bind

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

bind 函数的两个特点:

  1. 返回一个函数
  2. 可以传入参数

实现es5:

Function.prototype.bind = function (context) {
    var self = this;
    // 获取bind2函数从第二个参数到最后一个参数
    var args = Array.prototype.slice.call(arguments, 1);

    return function () {
        // 这个时候的arguments是指bind返回的函数传入的参数
        var bindArgs = Array.prototype.slice.call(arguments);
        return self.apply(context, args.concat(bindArgs));
    }

}

实现es6:

Function.prototype.bind = function (context) {
    var self = this;
    // 获取bind2函数从第二个参数到最后一个参数
    var [a, ...args] = [...arguments];

    return function () {
        // 这个时候的arguments是指bind返回的函数传入的参数
        var [a, ...bindArgs] = [...arguments];
        return self.apply(context, args.concat(bindArgs));
    }

}

猜你喜欢

转载自blog.csdn.net/zdhanunity/article/details/94644903