我正在查看Arrowlets source code,发现此部分位于顶部附近:
/*
* Box: a temporary (singleton) place to put stuff. Used as a helper for constructors with variadic arguments.
*/
function Box(content) {
Box.single.content = content;
return Box.single;
}
/* JavaScript hackery based on the strange semantics of "new":
* - Box() assigns Box.single.value, so Box.single has to be defined;
* - properties can be assigned to numbers (but have no effect);
* - when Box.single = 1 (or any non-Object), "new Box" returns "this". */
Box.single = 1;
Box.single = new Box;
Box.prototype.toString = function Box$prototype$toString() {
return "[Box " + this.content + "]";
}
我还查看了源代码中Box
的一些用法,看起来这是另一种传递多个参数的方法,但我真的不明白怎么做。此外,评论指出:
当Box.single = 1(或任何非对象)时,“new Box”返回“this”。
但我想只要用new
调用构造函数,就会返回this
。有人可以向我解释一下吗?
更新:
我很难理解为什么Box.single
必须设置为非对象才能使用此方法,以及使用new
运算符获得的技巧。 NodeJS repl的示例:
否new
并使用非对象
> function Box(content) {
... Box.single.content = content;
... return Box.single;
... }
Box.single = {}; // NOTE: Setting Box.Single to an Object
{}
> //NOTE: Not using the "new" operator at all
undefined
> Box(23)
{ content: 23 }
> Box.single
{ content: 23 }
> Box({'name': 'John'})
{ content: { name: 'John' } }
> Box.single
{ content: { name: 'John' } }
使用new
和对象
> function Box(content) {
... Box.single.content = content;
... return Box.single;
... }
undefined
> Box.single = {}; // Setting Box.single to an object
{}
> Box.single = new Box; // Using the new operator
{ content: undefined }
> Box({'name': 'John'})
{ content: { name: 'John' } }
> Box.single
{ content: { name: 'John' } }
与使用箭头:
中的方法相反> function Box(content) {
... Box.single.content = content;
... return Box.single;
... }
undefined
> Box.single = 1; // Setting Box.single to a Non-Object
1
> Box.single = new Box; // Using the new operator
{}
> Box(23)
{ content: 23 }
> Box({'name': 'John'})
{ content: { name: 'John' } }
> Box.single
{ content: { name: 'John' } }
似乎箭头方法只是一种简单的方式来完成简单的事情。我错过了什么?
答案 0 :(得分:2)
区别在于instanceof
:
...
Box.single = {};
Box.single = new Box; // with or without this line
Box(1) instanceof Box; // false
和
...
Box.single = 1;
Box.single = new Box;
Box(1) instanceof Box; // true
在第一种情况下,因为Box.single
是一个对象,根据JavaScript规则,new Box
上方的调用将返回Box.single
,这是一个普通的{}
对象。对new Box
或Box
的每次后续调用都会返回相同的普通对象。
在第二种情况下,Box.single
不是对象,因此new Box
会返回一个新的Box
对象并将其分配给Box.single
,并且每次后续调用new Box
1}}或Box
返回相同的Box
对象。
请注意,或许令人惊讶的是,new
不必返回this
;它可以通过调用obj
返回typeof(obj) == "object"
return obj
的任何typeof(obj) != "object"
(如果new
,则this
返回function Foo() {
this instanceof Foo; // true
}
function Bar() {
this instanceof Bar; // true
return new Foo();
}
(new Bar) instanceof Bar; // false
(new Bar) instanceof Foo; // true
)。 E.g:
new Box
这也是为什么可以使用Box
而不仅仅是a = Box(1);
b = new Box(2);
a === b; // true
:
{{1}}
答案 1 :(得分:1)
Arrowlets代码从不将此函数与“new”一起使用,除了这一个调用:
Box.single = new Box;
所以你对“this”的评论/关注仅与这一用途有关。你可以看到Box是一个函数,Box有一个叫做single的属性。通过上面的赋值,Box.single被设置为指向Box函数的实例 - 新Box返回的'this';
在将Box()作为构造函数调用之前,需要一些技巧才能使调用成功。在这种情况下,Box.single已设置为值1,因此设置单个内容:
Box.single.content = content;
将无害/忽略/但你想要想到它。
new Box;
呼叫。我们不希望构造函数抛出。因此诡计多端。 从构造函数调用返回后,Box.single被设置为实例化的Box()
开发人员正在尝试创建一个保留“内容”的单例。目标是使用Box()以将任意数量的参数打包在一起。这与使多参数JavaScript函数与Tuples一起工作有关,而Tuples是Arrowlets实现的基础。这里Box用于在数组中有超过2个元素时创建元组:
Tuple.fromArray = function Tuple$fromArray(array) {
switch (array.length) {
case 0:
case 1:
return array[0];
case 2:
return new Pair(array[0], array[1]);
default:
return new Tuple(Box(array));
}
}
当使用下面的构造函数创建元组时,如果传入Box,则框的内容将成为元组的“组件”
function Tuple() {
if (arguments[0] instanceof Box) {
var components = arguments[0].content;
} else {
[...omitted stuff...]
}
/* properties */
this.components = components;
this.length = components.length;
}
这就是所有这一切!