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 的构造函数(非常松散的描述:搜索 prototype
、class
和 javascript
以获得更高的准确性)。
在这种情况下,"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);
将创建 b
和 c
作为 _
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
到你第一次调用它的时候。
您现在有一个 _
对象。
我正在研究 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 的构造函数(非常松散的描述:搜索 prototype
、class
和 javascript
以获得更高的准确性)。
在这种情况下,"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);
将创建 b
和 c
作为 _
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
到你第一次调用它的时候。
您现在有一个 _
对象。