Skip to content

手写实现 call() apply() bind()函数

call、apply 和 bind 区别:

  • 相同点:

作用相同,都是动态修改 this 指向;都不会修改原先函数的 this 指向。

  • 异同点:

1、执行方式不同:

call 和 apply 是改变后页面加载之后就立即执行,是同步代码。

bind 是异步代码,改变后不会立即执行;而是返回一个新的函数。

2、传参方式不同:

call 和 bind 传参是一个一个逐一传入。

apply 可以使用数组的方式传入的 。

call 和 apply 不能使用剩余参数的方式传参,bind 可以使用剩余参数的方式传入(柯里化)。

3、修改 this 的性质不同:

call、apply 只是临时的修改一次,也就是 call 和 apply 方法的那一次;当再次调用原函数的时候,它的指向还是原来的指向。

bind 返回的函数对象会修改 this 的绑定,但原函数 this 指向依然不发生变化。

call 方法使用:

  • 可以传递两个参数。

第一个参数是指定函数内部中 this 的指向,也就是函数执行时所在的作用域:

(1)参数值为 null 或 undefined 或者 this,则等同于指向全局对象

(2)但不能为空

  • 第二个参数是函数调用时需要传递的参数,需要一个一个的传入(param1, aram2, param3... )

手写 call 方法

js
const foo = { a: 1 };
function bar(b, c) {
	console.log(this.a, b, c);
}

Function.prototype.myCall = function (context, ...args) {
	context = context || window;
	context.fn = this;
	context.fn(...args);
	delete context.fn;
};

bar.call(foo, 1, 2); //1 1 2
bar.myCall(foo, 1, 2); //1 1 2

apply 方法:

  • 可以传递两个参数。

  • 第一个参数是指定函数内部中 this 的指向,也就是函数执行时所在的作用域:

    (1)参数值为 null 或 undefined 或者 this,则等同于指向全局对象

    (2)但不能为空

  • 第二个参数是函数调用时需要传递的参数,是一个数组([param1, param2…])

js
const foo = { a: 1 };
function bar(b, c) {
	console.log(this.a, b, c);
}

Function.prototype.myApply = function (context, args) {
	context = context || window;
	context.fn = this;
	context.fn(...args);
	delete context.fn;
};

bar.apply(foo, [1, 2]); //1 1 2
bar.myApply(foo, [1, 2]); //1 1 2

bind 方法:

  • bind 方法用于指定函数内部的 this 指向(执行时所在的作用域),然后返回一个新函数。bind 方法并非立即执行一个函数。

第一个参数是指定函数内部中 this 的指向,也就是函数执行时所在的作用域:

(1)参数值为 null 或 undefined 或者 this,则等同于指向全局对象

(2)但不能为空

  • 第二个参数是函数调用时需要传递的参数,需要一个一个的传入(param1, param2, param3... )
js
const foo = { a: 1 };
function bar(b, c) {
	console.log(this.a, b, c);
}

Function.prototype.myBind = function (context, ...args) {
	context = context || window;
	context.fn = this;
	return function () {
		context.fn(...args);
		delete context.fn;
	};
};

bar.bind(foo, 1, 2)(); //1 1 2
bar.myBind(foo, 1, 2)(); //1 1 2

Released under the MIT License.