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

How does the _() function (object wrapper) in Underscore.js work?

我正在研究 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.

我想弄清楚 _(下划线)在这里的作用:我认为它用作构造函数和 returns 具有 underscore.js 中定义的所有函数的实例.这样用简单的语法调用函数会更方便。

狐狸例子:

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; 是如何工作的?

顶部的函数 "sort of like" 是 "sort of like" 在 JavaScript 中的 class 的构造函数(非常松散的描述:搜索 prototypeclassjavascript 以获得更高的准确性)。

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

开头的两个测试是为了防止误用:

if (obj instanceof _) return obj;

检查您没有将 _ class 的实例传递给构造函数(如果传递,它只是 return 那个实例)。这将停止:

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

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

第二次测试:

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

检查您在创建实例时是否正确使用了 new(或者相反,让您不必一直记住使用 new)。

在您的代码中调用时:

var test = _(obj);

_ 函数内部 this 的值将是全局作用域,因此不是 _ class 的实例。在这种情况下,它将使用 new 为您创建一个 _ class 和 return 的新实例。 (如果它不这样做,并且你没有使用 new,那么你将得不到新对象,最终会污染全局对象)。

如果像我上面的例子那样调用它(使用new),那么函数内部的this将是新创建的_对象。这个 是一个 instanceof _,因此将进入构造函数的主要部分:

this._wrapped = obj;

这会保存被包裹在新实例中的对象的副本。因此:

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

将创建 bc 作为 _ class 的新实例。 应该 使用 new 还是依靠构造函数为您做这件事是另一个问题。

_函数是递归的。你调用它,然后它第二次调用自己。一起来看看吧。

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

当您使用 obj={...} 执行 _(obj) 时,您的对象满足第二个 if 条件——this 不是 _ 的实例,因为它没有作为构造函数调用(this 是全局对象)。然后,它 returns new _(obj),调用 _ 作为构造函数。第二次,this 确实是 _ 的实例,因此两个条件都不满足。现在,它到达了最后一行。作为一个构造函数,它隐式 returns this 到你第一次调用它的时候。

您现在有一个 _ 对象。