关于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面向对象

kazama 9 years, 10 months ago

判断result包括临时的ctor都是在模拟new func()的行为,让bind后的结果在被new的时候依然按预期工作


 function a() { return 42; }
function b() { return {hello:"world"};}
console.log(new a(), new b());

洋葱的一天 answered 9 years, 10 months ago

首先,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是否是一个对象

如果有其他看法,欢迎继续交流。

淡意D优柔╮ answered 9 years, 10 months ago

Your Answer