在原生js中关于bind实现的一些疑惑
这里是原生js中bind的实现,我一些地方不是很理解,
if(!Function.prototype.bind){
Function.prototype.bind=function(obj){
var slice=[].slice,
args=slice.call.(arguments,1),
self=this,
nop=function(){},
bound=function(){
return self.apply(this, instanceof nop ? this:{obj||{}}),
args.concat(slice.call(arguments)))
};
nop.prototype=self.prototype;
bound.prototype=new nop();
return bound;
};
}
关于它的上下文是怎么变化的,我能够理解
但是我不太清楚,第一:
nop.prototype=self.prototype;
bound.prototype=new nop();
这里是在做什么?
第二是,这里的参数,关于参数数组的做法。
Deliy
9 years, 6 months ago
Answers
首先你这个 Polyfill 应该自己加了料进去了,那个
this, instance of nop
应该是多了一个
,
,具体可参考 MDN 的 Polyfill 写法:
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Glob...
先回答一下问题二:明白
bind
的用法就必须要知道
apply
的用法,
MDN
指出,
apply
是直接修改了函数内部的指向到第一个参数,并将第二个参数数组传参进函数并运行这个函数。也就是说
var obj = {test: function() { console.log(this, arguments) }},
func = obj.test;
obj.test("Hello", ",", "world", "!");
func.apply(obj, ["Hello", ",", "world", "!"]);
这两种运行方式是一样的。那么回到 Polyfill 中发现参数的写法是
args.concat(slice.call(arguments))
。
args
是将
bind
时候定义的除第一个参数外的其它参数,而此时的
arguments
是指函数调用时候的参数,通过数组的操作将这两个参数合并成一个数组传入函数内部。看个例子你可能更容易明白:
/** 代码接上 **/
var newFunc = func.bind(obj, "Hello", ",");
newFunc("world", "!");
那么再来回答问题一,这个是典型的属性继承的方法,本来使用
bound.prototype = self.prototype
就可以将原属性集成过来了,但是这样两个对象属性都指向同一个地方,修改
bound.prototype
将会造成
self.prototype
也发生改变,这样并不是我们的本意。所以通过一个空函数
nop
做中转,能有效的防止这种情况的发生。
二岩大明神
answered 9 years, 6 months ago