模拟apply/call/bind

本文深入探讨JavaScript中的call、apply与bind方法。详细解释了这些方法如何改变函数执行时的this指向,以及它们在参数处理上的差异。通过实例演示了call与apply的区别,即参数传递的不同形式,以及bind如何创建新函数并预置参数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 bindArgs = [...arguments];
        return self.apply(context, args.concat(bindArgs));
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值