11

背景:私の最新のプロジェクトでは大きなライブラリを使用できません。これは悲しいことです。addClass欠落している関数、hasClassremoveClass、 compatibleなど、どのライブラリからでも取得したいことがいくつかあります。そのため、別の機会に意見を求めたい小さなオブジェクトaddEventListenerを作成しましたが、私が望むように設定するのに少し苦労しました。

使いやすいように、作成時にオブジェクトがそれ自体の新しいインスタンスを返すようにします。

与えられた:

 $ = function() {
    this.name = "levi";

    return this;
};

console.log($());

$JavaScriptの風変わりな性質のため、代わりに DOMWindow を取得thisします。 私にとってさらに奇妙なのは、それがconsole.log(new $().name)適切に "levi" を返すことです。がウィンドウにバインドされている場合this、オブジェクトが適切に値を取得したのはなぜですか? . 新しいものを追加するだけconsole.log(new $())で機能します。ただし、毎回新しいことを書きたいわけではありません。だから私は試しました:

$ = function() {
    var obj = function() {
        this.name = "levi";
    };

    return new obj();
};

console.log($());

これは私が望むものを与えてくれますが、オブジェクトを作成する関数内にオブジェクトをラップするのは少し不必要に思えます。さらに、返されるオブジェクトは is objand not$です。比較テストは失敗します。

これを行うには、他にどのような方法がありますか? よりエレガントなソリューションはありますか?プロセス全体を再考することに何の不安もありません。私は JavaScript を使うのが得意だと思っていますが、新しい JavaScript を作成するのは初めてのことです。


次の解決策に問題があると思われる人はいますか?

$a = function() {};

$ = function() {
    if (!(this instanceof $)) {
        return new $();
    }

    this.name = "levi";

    return this;
};

//helper function
var log = function(message) {
    document.write((message ? message : '') + "<br/>");
};

log("$().name == window.name: " + ($().name == window.name)); //false
log("$().name: " + $().name); //levi
log("window.name: " + window.name); //result

log();

log("$a instanceof $: " + ($a instanceof $)); //false
log("typeof $a: " + (typeof $a)); //function
log("typeof $: " + (typeof $)); //function

私のすべてのテストで機能しているようです。

4

4 に答える 4

6

あなたが望むことを行う最も簡単な方法は次のとおりです(私は思います):

$ = function(){
    if (!(this instanceof $)){
     return new $;
    }
    this.name = 'levi'; 
    return this;
}

ただ戻るだけthisでは $ のインスタンスが作成されないという事実は、通常の関数として実行する方法が作成されるためです。その場合、 の値はthisグローバルオブジェクトを指します (ブラウザ内では: )。いわばjavascript生活の事実です。正しい値が表示されるのは、関数をコンストラクターとして呼び出すためです。コンストラクターは、そのコンストラクターのインスタンス (つまり、の新しいインスタンス) を返します。ただし、プロパティ を持つグローバル オブジェクト、つまりを返すため、'levi' も出力します。試してみると、グローバル変数になっていることがわかります。したがって、使用したくない場合は$thiswindow$()window.$()console.log(new $().name)$console.log($().name)namewindow.name$(); console.log(name)namenewキーワードを使用するたびに、関数が通常の関数として呼び出されているか、=== instanceof $コンストラクター関数内のインスタンス ( ) のコンストラクターとして呼び出されているかを確認してください。上記のメソッドを使用すると、インスタンスコンストラクターは、インスタンス化されているかどうかに関係なく、new常に$

おそらく、質問のタイトルを次のように言い換える必要があります。「それ自体のインスタンスを返すオブジェクト [コンストラクター] 」

たぶん、このブログエントリは特別な光を当てることができます.

于 2011-05-21T23:53:19.053 に答える
5

jQuery が行う方法thiswindow、(関数として呼び出される) かどうかを最初にテストし、そうであれば、それ自体の新しいインスタンスを返します。例えば:

var $ = function() {
    if(this === window) {
        return new $();
    }
    this.name = "levi";
    return this;
};

console.log($());

関数を通常どおり呼び出すと ( func()),thisが呼び出し元の と同じになるため、これが機能しますthis。(関連するが無関係ではない:obj.method()thisなるobj) デフォルトのスコープはであるため、 as として呼び出すとwindowthis内部$は になります。window$()

を使用して関数を呼び出すと、 JavaScript が新しいオブジェクトを作成し、そのオブジェクトに設定してnew関数を呼び出します。this

thisこのソリューションは、最初にisかどうかをテストwindowし、したがって like と呼ばれるために機能し$()ます。のように呼び出された場合は$()、 が返されnew $()ます。それ以外の場合は、で呼び出されnew $()、期待どおりに動作します。

于 2011-05-21T22:47:14.333 に答える
4
>  $ = function() {
>     this.name = "levi";
> 
>     return this; };
> 
> console.log($());

$ の代わりに DOMWindow を取得します

$を関数として呼び出すと、そのように呼び出される関数の場合と同様に、そのthisキーワードがグローバル オブジェクトに設定されます。

これは JavaScript の風変わりな性質のため

Javascript のthisキーワード* は、動作するように指定されているとおりに動作します。他の言語とは異なりますが、それが機能する方法です。

さらに奇妙なのは、console.log($().name) が適切に「levi」を返すことです。

$を関数として呼び出す場合、そのthisキーワードはグローバル オブジェクトなので、次のようになります。

this.name = 'levi';

'levi' の値を持つnameと呼ばれるグローバル オブジェクトのプロパティを作成します。何が起こっているかを知っていればおかしくありません。:-)

new console.log(new $()) を追加するだけで機能します。

これが、javascript でコンストラクターを呼び出す方法です。関数がnewで呼び出されると、そのthisキーワードが新しく構築されたオブジェクトに設定されるため、this.nameそのオブジェクトの新しいプロパティが作成されます。ちなみにreturn this冗長ですが、コンストラクタはデフォルトでこれを返します。

> $ = function() {
>     var obj = function() {
>         this.name = "levi";
>     };
> 
>     return new obj(); };

console.log($()); これは私が望むものを与えてくれますが、オブジェクトを作成する関数内にオブジェクトをラップするのは少し不必要に思えます。さらに、それはタイプ obj であり、タイプ $ ではありません

おそらく、ECMA-262 で指定された値の 1 つだけを返すことができるtypeofを使用しています。その短いリスト (オブジェクト、数値、文字列などを含む) には$が含まれていません。

これを行うには、他にどのような方法がありますか?

すでに発見したアプローチ、Lasse Reichstein Nielsen のクローン (Doublas Crockford によって "beget" として普及された) と Richard Cornford のモジュール パターンを使用できます。Google を使用してください。上記のすべてについて、非常に多くの投稿があります。

于 2011-05-21T22:56:52.073 に答える
1

次のようなものを試してください。

function $(name){
    if( !(this instanceof arguments.callee) ){
        return new arguments.callee(name);
    }
    this.name = name;
    return this;
}

更新

@レヴィモリソン

編集:誰かが次の解決策に何か問題があると思いますか?

あなたが尋ねたので、私はdocument.writeに完全に恋しているわけではありません
代わりにこれを試してください:

var log = function(message){
    if(message){
        document.body.appendChild(document.createTextNode(message));
    }
    document.body.appendChild(document.createElement('br'));
}
于 2011-05-21T23:04:21.510 に答える