0

Arrowletsのソース コードを調べていたところ、上部近くに次のセクションが見つかりました。

/*
 * 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' } }

Arrowletsのメソッドを使用するのとは対照的に:

> 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' } }

アローレットのアプローチは、単純なことを達成するための複雑な方法にすぎないようです。私は何が欠けていますか?

4

2 に答える 2

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 BoxBox

2 番目のケースでは、Box.singleはオブジェクトではないためnew Box、新しいBoxオブジェクトを返し、それを に代入しBox.single、その後のすべての呼び出しnew BoxまたはBox同じBoxオブジェクトを返します。

驚くかもしれnewませんが、return する必要はありませんthis。(if , then returns )を呼び出すことで、objどこにでも返すことができます。例えば:typeof(obj) == "object"return objtypeof(obj) != "object"newthis

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

new Boxこれが、 の代わりに を使用できる理由でもありBoxます。

a = Box(1);
b = new Box(2);
a === b; // true
于 2013-11-24T17:32:06.877 に答える
1

Arrowlets コードは、この 1 つの呼び出しを除いて、この関数を「new」で使用することはありません。

Box.single = new Box;

したがって、「これ」に関するコメント/懸念は、この 1 つの使用にのみ関連しています。Box は関数であり、Box には single というプロパティがあることがわかります。上記の割り当てにより、Box.single は Box 関数のインスタンス (new Box によって返される「this」) を指すように設定されます。

Box() がコンストラクターとして呼び出される前に、呼び出しを成功させるためにいくつかのトリックが必要です。その場合、Box.single の値は 1 に設定されているため、single の内容は次のように設定されます。

Box.single.content = content;

無害/無視/どう考えても。「コンテンツ」は未定義になります

new Box;

電話。コンストラクターにスローさせたくありません。したがって、トリック。コンストラクター呼び出しから戻ると、Box.single はインスタンス化された Box() に設定されます。

開発者は、「コンテンツ」を保持するシングルトンを作成しようとしています。目標は、任意の数の引数を一緒にパッケージ化するために Box() を使用することです。これは、Arrowlets 実装の根底にあるタプルで多数のパラメーターを使用する JavaScript 関数を機能させることに関係しています。ここでは、配列に 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));
    }
}

以下のコンストラクタで Tuple を作成し、Box を渡すと、Box の内容が Tuple の「コンポーネント」になります。

function Tuple() {
    if (arguments[0] instanceof Box) {
        var components = arguments[0].content;
    } else {
        [...omitted stuff...]
    }
    /* properties */
    this.components = components;
    this.length = components.length;
}

それだけです!

于 2013-10-30T01:14:24.330 に答える