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

fra*_*eng 2 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.
Run Code Online (Sandbox Code Playgroud)

我试图找出_(下划线)在这里做什么:我认为它作为构造函数并返回一个实例,其中包含在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"
Run Code Online (Sandbox Code Playgroud)

但是这背后的机制是什么呢?

怎么样this._wrapped = obj;

Tri*_*und 6

顶部的函数"有点像"一个构造函数,用于"有点像"JavaScript中的类(一个非常宽松的描述:搜索prototype,class并且javascript更准确).

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

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

if (obj instanceof _) return obj;
Run Code Online (Sandbox Code Playgroud)

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

var a = {...};
var b = new _(a);
var c = new _(b);
Run Code Online (Sandbox Code Playgroud)

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

第二个测试:

if (!(this instanceof _)) return new _(obj);
Run Code Online (Sandbox Code Playgroud)

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

在您的代码中调用时:

var test = _(obj);
Run Code Online (Sandbox Code Playgroud)

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

如果在上面的例子中使用它(使用new),那么this函数内部将是新创建的_对象.这是一个instanceof _,所以将进入构造函数的主要部分:

this._wrapped = obj;
Run Code Online (Sandbox Code Playgroud)

它保存了包装在新实例中的对象的副本.从而:

var a = {...};
var b = _(a);
var c = new _(a);
Run Code Online (Sandbox Code Playgroud)

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