关于underscore1.3.3中_.bind的一些小疑问
最近学习underscore1.3.3的源代码,看到了_.bind的实现,有些不解。
具体代码如图:
我是从以下这段代码开始有不解的:
我看到一些人说var result = func.apply(self, args.concat(slice.call(arguments)))的作用是将function强制转换成一个类的构造函数,这如何理解呢?然后为什么要判断result的类型呢,是基于什么样的考虑呢?利用一个ctor构造函数又是处于什么样的考虑,希望有前辈可以解答一下,谢谢
underscore web web前端开发 JavaScript javascript面向对象
Answers
首先,bind方法返回的是一个函数,所以如果有如下行为,则不能达到预期:
var OtherCtor = _.bind(Ctor, content);
new OtherCtor(); //根据bind的语义,这里应该要返回一个Ctor实例
截取MDN中对bind方法的描述:
一个绑定函数也能使用 new 操作符 创建对象:这种行为就像把原函数当成构造器。提供的 this 值被忽略,同时调用时的参数被提供给模拟函数。
bind的目的是关联一个执行上下文,而对于构造函数而言,返回的新函数破坏了原来的原型之间的关系。所以会有一个特殊处理:
if(!(this instanceof bound)) // 这个是判断函数不作为构造函数使用时
那么下面的代码就是在作为构造函数被调用时,因为我们依然希望返回的是一个func对象,即保留原本的原型关系,所以本来是可以这样的:
new func().apply(...) // 有什么不对?
上面这句的语法是错误的,我即希望用
new
,又希望动态传参,那么就只要借用一个额外的变量了。
ctor.prototype = func.prototype;
var self = new ctor();
var result = func.apply(self, ...);
这样就即保留了原型关系,又调用了构造函数,似乎完成了,但是构造函数被调用时虽然关联了上下文为self,但是还是有区别:
当使用new调用构造函数时,如果构造函数返回值非对象(包括没有返回值),则返回this,如果构造函数返回对象,则应该返回这个对象
所以为了彻底模拟这个行为做了最后的判断。
Object(result) === result // 将result转成对象,看和原来的是否完全相等,来判断result是否是一个对象
如果有其他看法,欢迎继续交流。