区别
call、apply、bind
本质都是改变 this
的指向,不同点 call、apply
是直接调用函数,bind
是返回一个新的函数。call
跟 apply
就只有参数上不同。
区别就是call()
方法接受的是参数列表,而apply()
方法接受的是一个参数数组。
bind
实现
- 箭头函数的
this
永远指向它所在的作用域
- 函数作为构造函数用
new
关键字调用时,不应该改变其 this
指向,因为 new绑定
的优先级高于 显示绑定
和 硬绑定
代码实现
Function.prototype.myBind = function (thisArg, ...args) { if (typeof this !== 'function') { throw Error('must be a function'); } const self = this, nop = function () {}, bound = function (...selfArgs) { return self.apply( this instanceof nop ? this : thisArg, args.concat(selfArgs) ); };
if (this.prototype) { nop.prototype = this.prototype; } bound.prototype = new nop(); return bound; };
|
测试
const bar = function() { console.log(this.name, arguments); };
bar.prototype.name = 'bar';
const foo = { name: 'foo' };
const bound = bar.mybind(foo, 22, 33, 44); new bound(); bound();
|
Call & Apply
Call
bind
是封装了 call
的方法改变了 this
的指向并返回一个新的函数,那么 call
是如何做到改变 this
的指向呢?原理很简单,在方法调用模式下,this
总是指向调用它所在方法的对象,this
的指向与所在方法的调用位置有关,而与方法的声明位置无关(箭头函数特殊)。先写一个小 demo 来理解一下下。
const foo = { name: 'foo' };
foo.fn = function() { console.log(this.name); };
|
我们可以利用this
的这个特性来实现call
Function.prototype.myCall = function (thisArg, ...args) { if (typeof this !== 'function') { throw new TypeError('Error'); } thisArg = thisArg || window; thisArg.fn = this; const result = thisArg.fn(...args); delete thisArg.fn; return result; };
|
Apply
Function.prototype.myApply = function (thisArg) { if (typeof this !== 'function') { throw new TypeError('Error'); } thisArg = thisArg || window; thisArg.fn = this; const args = arguments[1]; const result = thisArg.fn(...args); delete thisArg.fn; return result; };
|
测试
const bar = function () { console.log(this.name, arguments); };
bar.prototype.name = 'bar';
const foo = { name: 'foo', };
bar.myCall(foo, 1, 2, 3); bar.myApply(foo, [1, 2, 3]);
|
完~
参考