使用原生JavaScript实现bind中的一个小问题

发布于 2022-09-04 14:54:23 字数 439 浏览 15 评论 0

最近看了一篇颜大的文章从一道面试题的进阶,到“我可能看了假源码”

看到后面发现有一个不懂的地方:

图片描述

为了实现红框内的兼容:

图片描述

其中红框圈出的代码小弟不是很懂,希望有大神能够指点一二

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

许久 2022-09-11 14:54:23

其主要原因里面也说了,你可能没有想一下真实调用的场景。
bind除了具有绑定this上下文的作用,其还具有类似于函数柯里化,提前绑定一些参数的作用。

如下场景:

function Person(country, name, age){
  this.country = country;
  this.name = name;
  this.age = age;
}

var ChinesePerson = Person.bind(undefined, 'China');

var person1 = new ChinesePerson('LiLi',14);

如果我们没有你图中的红圈标注的,就会导致上面的代码报错。即使我们传入了一个已经声明好的对象obj进去,那么只会修改obj上的属性,不符合 new构造函数 实例化返回一个新对象的标准。

找回味觉 2022-09-11 14:54:23

搞了好久细节,终于搞清楚了跟你说说,也在这里做个笔记,不是很会描述,见谅:

首先,先看bind文档,经过bind的方法,如果使用new的话,会忽略bindcontext,而是用新生成的实例对象作为this

其次,再看看instanceof的文档instanceof返回的结果是: 原型链中是否存在一个构造函数的 prototype 属性

instanceof 运算符用来检测 constructor.prototype 是否存在于参数 object 的原型链上。

所以,这里用F先保存当前的prototype,然后通过bound.prototype = new F()bound继承this.prototype里面的属性,而通过new bound()生成的对象的原形链中就会含有this.prototype。举个栗子说明继承原形链:

function fn(a,b,c) { console.log(this) };
fn.prototype.test1 = function(){ console.log("test1"); }
var fn1 = fn.bind(1);
var instance = new fn1();
instance.test1(); // 输出:test1,说明fn1继承了fn.prototype上面的属性

最后,由于是通过bound.prototype = new F(),所以当使用new的时候,this instanceof F会返回true。那么就会把方法内部的this绑定成当前的实例,就达到了上面第一条说的效果

几个问题:

下面的都是前辈们指出来的,所以我非原创,不拿任何credit。

他的这个栗子其实已经很好地实现了需要,不过吹毛求疵一点,讨论两个问题:

第一个问题:使用context||this是否合理?作者的目的是在不使用new的情况下,没有传入context时,使用自己的this代替。这个其实有点多此一举,首先fn.apply(undefined)也是可以的。而且当对fn使用严格模式的时候,会出现this指向window的问题,应该是undefined

function fn() { 'use strict'; console.log(this); } 
fn.bind()(); // 应该是undefined,但是栗子中的bind会返回window

第二个问题:使用F来传递原形的属性,而不是直接通过bound.prototype = this.prototype,我看原作者说的是为了防止污染this,但是我没有理解怎么污染this的。反而会造成下面的问题:

function fn(){ console.log(this) };
var fn1 = fn.bind(1);
var instance = new fn1();
console.log(instance.__proto__ === fn.prototype); // 原生的bind应该返回true,而文中bind的栗子返回的是false

最后两句题外话

建议看看他的第二篇es5-shims的实现,还是挺有启迪性的。

同时,今天我在讨论这个问题的细节的时候,被前辈们教训了,很多东西不需要考虑得过于全面,在写代码的时候,只要满足你的需要就够了,选择实现我会用的方式,代码最少化。然而我上面很多分析都有点过了~哈哈~共勉~~

堇色安年 2022-09-11 14:54:23

说下后面几个圈的知识点

看看代码:

var F = function(){};
var B = function(){console.log(this instanceof F);};
new B();//false
B.prototype = new F();//将B原型指向F去,那么new出来的实例 instanceof F,也就true了
new B();//true

通过整理原型链来做判断最终的bound是new 调用出来还是直接调用。

至于这块,没咋去理解= =
clipboard.png

大概是保证new bound出来的实例能顺着原型链一直链到被绑定函数的原型链上,保证原型链一致吧。

吖咩 2022-09-11 14:54:23

其实你不用管那么多,只要是用new实例了一个函数,里面的this就会指向其自身,什么bind的一律失效

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文