html5 - 使用原生JavaScript实现bind中的一个小问题
PHP中文网
PHP中文网 2017-04-11 12:32:27
[JavaScript讨论组]

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

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

为了实现红框内的兼容:

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

PHP中文网
PHP中文网

认证0级讲师

全部回复(4)
PHPz

其主要原因里面也说了,你可能没有想一下真实调用的场景。
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构造函数 实例化返回一个新对象的标准。

阿神

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

首先,先看 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的实现,还是挺有启迪性的。

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

高洛峰

说下后面几个圈的知识点

看看代码:

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 调用出来还是直接调用。

至于这块,没咋去理解= =

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

迷茫

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

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号