连续bind返回值的个人理解

1,445 阅读2分钟

对连续bind的一些理解:

先贴上自己理解的手写bind实现,参考了一些大佬的理解:

Function.prototype.myBind = function(asThis, ...arg) {
    let _this = this;
    if (typeof _this !== 'function') {
        throw new Error('not a function');
    }
    let newFn = function() {
        console.log('打印的asThis', asThis);//帮助理解
        console.log('打印的_this', _this);//帮助理解
        return _this.apply(
            newFn.prototype.isPrototypeOf(this) ? this : asThis,
            [...arg, ...arguments]
        )
    }
    newFn.prototype = _this.prototype;
    return newFn;
}

另外

var fNOP = function () {};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();

这是为了防止原型链篡改。但自己认为没有必要这样写。

自己的测试运行代码:

function fn(age) {
    console.log(arguments);
    console.log(this.name, age);
}

let o1 = { name: 'xiao_ming' },
    o2 = { name: 'xiao_hong' },
    o3 = { name: 'xiao_jun' };

let a = fn.bind(o1, 10);
let b = a.bind(o2, 22);
let c = b.bind(o3, 99);
c(18); //xiao_ming 15
fn.bind(o1, 10).bind(o2, 22).bind(o3, 99)(18); //xiao_ming 10

fn.myBind(o1, 10).myBind(o2, 22).myBind(o3, 99)(18); //xiao_ming 10

浏览器打印出如下内容:

QQ拼音截图20210405005724.png 自己的理解: 1、bind()方法会创建一个新的函数; 2、bind()的第一个参数为新函数的this的指向,后边的参数会作为新函数的前几个参数传入; 3、新函数在运行时,会调用原函数; 4、连续bind会产生闭包,算是一种函数柯里化的应用。 fn.bind(o1, 10).bind(o2, 22).bind(o3, 99)(18);相当于:

let a = fn.bind(o1, 10);
let b = a.bind(o2, 22);
let c = b.bind(o3, 99);
c(18);

c(18)在运行的时候,会调用b函数,并把参数99, 18(bind直接绑定的参数会在前)传给b函数,b函数内部this指向o3;

b在运行的时候,会调用a函数,并把参数22, 99, 18传给a函数,a函数内部this指向o2;

a在运行的时候,会调用fn函数,并把参数10, 22, 99, 18传给fn函数,fn函数内部this指向o1;

即最后执行的时候相当于fn.apply(o1, 10, 22, 99, 18),this指向为o1,且fn会接收到10、22、99、18这四个参数。

上边的实现的myBind和js自身的bind有不一样的地方

测试代码如下:

let a = fn.bind(o1); //自带的bind
let aa = new a();
let b = fn.myBind(o1); //自己实现的bind
let bb = new b();

console.log(a.prototype); //undefined
console.log(aa.__proto__ === a.prototype); //false
console.log(aa.__proto__ === fn.prototype); //true

console.log(b.prototype); //{constructor: ƒ}
console.log(bb.__proto__ === b.prototype); //true
console.log(bb.__proto__ === fn.prototype); //true

产生了这些差异,自己的理解:

bind()方法会创建一个新的函数,这个新函数相当于原函数的副本,但在原型链上并不存在关系。新函数的prototype为undefined

(同样typeof值为'function',但prototype属性值为undefined的还有任意箭头函数,console.log等)

通过新函数new出来的实例,这个实例的__proto__指向原函数的prototype。理解为这个实例是由原函数这个构造函数生成的。所以使用new的时候,bind绑定的this并不能生效。new的优先级高于bind

如何解决自己实现bind的这一不一致的问题,暂时没找到,希望读者可以帮忙解决这一不一致。

参考文章:

一次搞定前端“四大手写”

前端面试题——自己实现bind