// bind会返回一个硬绑定的新函数,新函数会使用指定的第一个thisCtx去调用原始函数,并将其它参数传给原始函数。 硬绑定会降低函数的灵活性,在绑定之后不能通过显式或硬绑定的方式改变this,只能通过new改变 // softBind 会对指定的函数进行封装,首先检查调用时的 this,如果 this 绑定到全局对象或者 undefined,那就用指定的thisCtx 去调用函数,否则不会修改 this Function.prototype.myBind = function (context, ...args) { const self = this; const fn = function (...newArgs) { console.log("this", this); // 链式调用的时候 { a: 6 } console.log("context", context); //{ a: 2 } // 优先判断是否来自new 调用之后的实例,是的话 this 不变 self.apply(this instanceof fn ? this : context, args.concat(newArgs)); }; fn.prototype = Object.create(this.prototype); return fn; }; function f1(b) { console.log(this.a, b); } let fb11 = f1.myBind({ a: 1 }, 10); let bindFn1 = new fb11(); // undefined 10 因为 new 调用优先级高于 bind 改变的this 指向 let fb22 = f1.myBind({ a: 2 }, 10); fb22(); // 2,10 let fb33 = f1.myBind({ a: 3 }, 10); fb33(); // 3,10 let fb66 = fb22.myBind({ a: 6 }, 10)(); // 2,10 // fb66(); // 2,10 // 结论:bind方法链式调用,都以第一次bind绑定为准,所以叫硬绑定,原理为 下一次 调用bind的方法为上一个bind方法返回的闭包,已经将 context、args 存储好并固定返回了 // 参考链接:https://juejin.cn/post/6921897996258918413 // bind方法分别多次调用,各自都可绑定成功 console.log("================="); // softBind globalThis 代表获取当前环境下的全局对象 Function.prototype.softBind = function (context = globalThis, ...args) { const self = this; const fn = function (...newArgs) { // new 的时候和链式调用 softBind 的时候打印 if (this !== globalThis) { console.log("this", this); // 链式调用的时候 { a: 6 } console.log("context", context); //{ a: 2 } } self.apply( this instanceof fn ? this : !this || this === globalThis ? context : this, args ); }; fn.prototype = Object.create(this.prototype); return fn; }; let fs22 = f1.softBind({ a: 2 }, 10); fs22(); // 2 10 let fs33 = f1.softBind({ a: 3 }, 10); fs33(); // 3 10 let fs66 = f1.softBind({ a: 2 }, 10).softBind({ a: 6 }, 10); fs66(); //6 10 let fs11 = f1.softBind({ a: 1 }, 10); let softbindFn1 = new fs11(); // undefined 10 因为 new 调用优先级高于 bind 改变的this 指向
标签:10,bind,softBind,js,let,context,fn From: https://www.cnblogs.com/beileixinqing/p/16597249.html