扫码关注官方订阅号
最近看了一篇颜大的文章从一道面试题的进阶,到“我可能看了假源码”
看到后面发现有一个不懂的地方:
为了实现红框内的兼容:
其中红框圈出的代码小弟不是很懂,希望有大神能够指点一二
认证0级讲师
其主要原因里面也说了,你可能没有想一下真实调用的场景。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构造函数 实例化返回一个新对象的标准。
new构造函数
搞了好久细节,终于搞清楚了跟你说说,也在这里做个笔记,不是很会描述,见谅:
首先,先看 bind文档,经过bind的方法,如果使用new的话,会忽略bind的context,而是用新生成的实例对象作为this。
bind
new
context
this
其次,再看看 instanceof的文档,instanceof返回的结果是: 原型链中是否存在一个构造函数的 prototype 属性。
instanceof
原型链中是否存在一个构造函数的 prototype 属性
instanceof 运算符用来检测 constructor.prototype 是否存在于参数 object 的原型链上。
所以,这里用F先保存当前的prototype,然后通过bound.prototype = new F()让bound继承this.prototype里面的属性,而通过new bound()生成的对象的原形链中就会含有this.prototype。举个栗子说明继承原形链:
F
prototype
bound.prototype = new F()
bound
this.prototype
new bound()
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绑定成当前的实例,就达到了上面第一条说的效果
this instanceof F
true
下面的都是前辈们指出来的,所以我非原创,不拿任何credit。
他的这个栗子其实已经很好地实现了需要,不过吹毛求疵一点,讨论两个问题:
第一个问题:使用context||this是否合理?作者的目的是在不使用new的情况下,没有传入context时,使用自己的this代替。这个其实有点多此一举,首先fn.apply(undefined)也是可以的。而且当对fn使用严格模式的时候,会出现this指向window的问题,应该是undefined。
context||this
fn.apply(undefined)
fn
window
undefined
function fn() { 'use strict'; console.log(this); } fn.bind()(); // 应该是undefined,但是栗子中的bind会返回window
第二个问题:使用F来传递原形的属性,而不是直接通过bound.prototype = this.prototype,我看原作者说的是为了防止污染this,但是我没有理解怎么污染this的。反而会造成下面的问题:
bound.prototype = this.prototype
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的实现,还是挺有启迪性的。
es5-shims
同时,今天我在讨论这个问题的细节的时候,被前辈们教训了,很多东西不需要考虑得过于全面,在写代码的时候,只要满足你的需要就够了,选择实现我会用的方式,代码最少化。然而我上面很多分析都有点过了~哈哈~共勉~~
选择实现我会用的方式,代码最少化
其实你不用管那么多,只要是用new实例了一个函数,里面的this就会指向其自身,什么bind的一律失效
微信扫码关注PHP中文网服务号
QQ扫码加入技术交流群
Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
PHP学习
技术支持
返回顶部
其主要原因里面也说了,你可能没有想一下真实调用的场景。
bind除了具有绑定this上下文的作用,其还具有类似于函数柯里化,提前绑定一些参数的作用。
如下场景:
如果我们没有你图中的红圈标注的,就会导致上面的代码报错。即使我们传入了一个已经声明好的对象obj进去,那么只会修改obj上的属性,不符合
new构造函数实例化返回一个新对象的标准。搞了好久细节,终于搞清楚了跟你说说,也在这里做个笔记,不是很会描述,见谅:
首先,先看
bind文档,经过bind的方法,如果使用new的话,会忽略bind的context,而是用新生成的实例对象作为this。其次,再看看
instanceof的文档,instanceof返回的结果是:原型链中是否存在一个构造函数的 prototype 属性。所以,这里用
F先保存当前的prototype,然后通过bound.prototype = new F()让bound继承this.prototype里面的属性,而通过new bound()生成的对象的原形链中就会含有this.prototype。举个栗子说明继承原形链:最后,由于是通过
bound.prototype = new F(),所以当使用new的时候,this instanceof F会返回true。那么就会把方法内部的this绑定成当前的实例,就达到了上面第一条说的效果几个问题:
他的这个栗子其实已经很好地实现了需要,不过吹毛求疵一点,讨论两个问题:
第一个问题:使用
context||this是否合理?作者的目的是在不使用new的情况下,没有传入context时,使用自己的this代替。这个其实有点多此一举,首先fn.apply(undefined)也是可以的。而且当对fn使用严格模式的时候,会出现this指向window的问题,应该是undefined。第二个问题:使用
F来传递原形的属性,而不是直接通过bound.prototype = this.prototype,我看原作者说的是为了防止污染this,但是我没有理解怎么污染this的。反而会造成下面的问题:最后两句题外话
建议看看他的第二篇
es5-shims的实现,还是挺有启迪性的。同时,今天我在讨论这个问题的细节的时候,被前辈们教训了,很多东西不需要考虑得过于全面,在写代码的时候,只要满足你的需要就够了,
选择实现我会用的方式,代码最少化。然而我上面很多分析都有点过了~哈哈~共勉~~其实你不用管那么多,只要是用new实例了一个函数,里面的this就会指向其自身,什么bind的一律失效