Underscore.js中的_()函数(对象包装器)如何工作?

时间:2015-06-09 10:58:41

标签: javascript underscore.js

我正在研究underscore.js,我陷入了第一个功能。

// Create a safe reference to the Underscore object for use below.
var _ = function(obj) {
    if (obj instanceof _) return obj;
    if (!(this instanceof _)) return new _(obj);
    this._wrapped = obj;
  };

// Test Examples
var obj = {
    name : 'Francis',
    gender: 'male'
}
var test = _(obj);
console.log(test); // _ {_wrapped: Object}
                   // Why statement this._wrapped = obj; still got executed?

var Man = function() {
    this.age = 30;
    this.people = "John";
    return this;
    this.man = "me";
}
var me = new Man();
console.log(me) // Man {age: 30, people: "John"}
                // There is no "man" property because function Man returns
                // before executing to the last statement.

我试图找出_(下划线)在这里做了什么:我认为它作为构造函数并返回一个实例,其中包含在underscore.js中定义的所有函数。因此,用简单的语法调用函数会更方便。

Fox示例:

var anotherList = [1, 2];
_.each(anotherList, alert); // alert "1", "2"

var anotherObj = {"name": "H"};
var anotherObj = _(anotherObj);
anotherObj.each(alert); // alert "H"

但这背后的机制是什么?

this._wrapped = obj;如何运作?

2 个答案:

答案 0 :(得分:5)

顶部的功能"有点像"某种东西的构造函数,有点像" JavaScript中的一个类(非常宽松的描述:搜索prototypeclassjavascript以获得更高的准确性。)

在这种情况下,"类"有一个成员(._wrapped),它被设置为指定的对象(obj)。 (在其他地方,在underscore.js中,"类"的所有功能都将使用.prototype添加。)

一开始的两个测试是为了防止错误使用:

if (obj instanceof _) return obj;

检查您是否没有将_类的实例传递给构造函数(如果这样做,它只返回该实例)。这将停止:

var a = {...};
var b = new _(a);
var c = new _(b);

创建一个双重包装的对象(c将与b相同。)

第二次测试:

if (!(this instanceof _)) return new _(obj);

在创建实例时检查您是否正确使用了new(或者相反,允许您不必记住始终使用new

在代码中调用时:

var test = _(obj);

this函数内_的值将是全局范围,因此不是_类的实例。在这种情况下,它将使用new来创建_类的新实例并将其返回。 (如果它没有这样做,并且你没有使用new,那么你就不会得到一个新对象,最终会污染全局对象。)

如果在上面的示例中调用它(使用new),则函数内的this将是新创建的_对象。这个成为instanceof _,因此将继续进行构造函数的主要部分:

this._wrapped = obj;

保存包装在新实例中的对象的副本。因此:

var a = {...};
var b = _(a);
var c = new _(a);

将同时创建bc作为_类的新实例。无论你应该使用new,还是依赖构造函数为你做这件事都是另一个问题。

答案 1 :(得分:4)

_函数是递归的。你打电话给它,然后它第二次称自己。我们来看看。

var _ = function(obj) {
    if (obj instanceof _) return obj;
    if (!(this instanceof _)) return new _(obj);
    this._wrapped = obj;
  };

当您使用_(obj)执行obj={...}时,您的对象符合第二个if条件 - this不是_的实例,因为它是没有被称为构造函数(this是全局对象)。然后,它返回new _(obj),调用_作为构造函数。第二次,this确实是_的一个实例,所以这两个条件都没有实现。现在,它到达最后一行。作为构造函数,它会在您第一次调用它时隐式返回this

您现在有一个_对象。