2012-06-15 23 views
7

「JavaScriptライブラリを作成する」方法を先読みしていましたが、私はこれらのコードを読んで私の髪を引き裂こうとしました。これらのコードはどのように正確に機能しますか?

ここで結び目に私の脳を得たコードです:

if (window === this) { 
    return new _(id); 
} 

_(ID)は、このコードが含まれているだけの関数名です。あなたがそれを見直す必要がある場合、残りのコードはここにあります。

function _(id) { 

// About object is returned if there is no 'id' parameter 
var about = { 
    Version: 0.5, 
    Author: "Michael Jasper", 
    Created: "Fall 2010", 
    Updated: "23 November 2011" 
}; 

if (id) { 

    // Avoid clobbering the window scope: 
    // return a new _ object if we're in the wrong scope 
    if (window === this) { 
     return new _(id); 
    } 

    // We're in the correct object scope: 
    // Init our element object and return the object 
    this.e = document.getElementById(id); 
    return this; 
    } else { 
    // No 'id' parameter was given, return the 'about' object 
    return about; 
    } 
}; 

以前は「新しい機能を返す」ことはありませんでしたが、その機能の仕組みを理解したいと思います。

コードの他の部分:

_.prototype = { 
    hide: function() { 
      this.e.style.display = 'none'; 
      return this; 
    } 

    show: function() { 
      this.e.style.display = 'inherit'; 
      return this; 
    } 
}; 

私はこのコードは_オブジェクトに新しいメソッドを追加することを知っているが、なぜ彼らは「これを返す」のですか?私はそれを使わずに試してみました。

最後に一つ、記事へのリンクはhttp://www.mikedoesweb.com/2012/creating-your-own-javascript-library/

+0

これが返されますか?だから、後に何かを追加することができますか?ちょうど推測 – Anonymous

+6

'これを返す 'は' magic()。do()。stuff() 'のように連鎖を有効にします。 –

+0

ええ、連鎖は私が言ったことです、それはjqueryのようですが、jqueryは少し複雑で多くのオブジェクトを返します。 – Anonymous

答えて

16

コードの最初のビットは、基本的に「コンストラクタ」関数が呼び出されたかを検出しようとしている...

JavaScriptでは、次の2つの方法でオブジェクトを作成する機能を使用することができます。

function _(id) { 
    this.someProperty = "stuff"; 
    //Do more stuff to "this" 
    return this; 
} 

//in this scenario, the "this" object will be the window object 
var myObject = _(id); 
console.log(window.someProperty); //outputs "stuff"; 
console.log(myObject.someProperty); //outputs "stuff"; 

//in this scenario, the "this" object is what get's actually returned... 
var myObject = new _(id); 
console.log(window.someProperty); //outputs "undefined" 
console.log(myObject.someProperty); //outputs "stuff" 

ので、

if (window === this) { 
    return new _(id); 
} 

のためのチェックが誤ってnewキーワードを指定せずにコンストラクタを呼び出さないことを確認するために、単にそこにあります。これは悪いです。オブジェクトに割り当てるプロパティはすぐにwindow ...に割り当てられます。これは悪いことです。あなたの2番目の質問については


、著者はこれが便利で見栄えのオブジェクトの操作を可能にするfluent interface design pattern

として、各メソッドの最後にreturn this;を使用しています。この一般的な例は、jQueryの、ここですることができます1つのオブジェクトの上にチェーン・メソッド...

$(".some-css-selector").click(function() { 
    ... do something to the selected objects during the "click" event 
}).keyup(function() { 
    ... do something to the same objects during the "keyup" event 
}); 

EDIT:ダグラスから

:以下W3Geekのコメントに応答して、もう少し追加情報Crockfordの著書「Javascript:The Good Parts」(70ページしかないのですが、読んでみる価値があります)。


のJavascriptのnew演算子は、オペランドのプロトタイプメンバーから継承する新しいオブジェクトを作成し、thisに新しいオブジェクトを結合、オペランドを呼び出します。これにより、オペランド(コンストラクタ関数である方がよい)は、新しいオブジェクトがリクエスタに返される前にそれをカスタマイズする機会を与えます。

`new演算子を使用するのを忘れた場合、通常の関数呼び出しが行われ、新しいオブジェクトではなくグローバルオブジェクトにバインドされます。つまり、新しいメンバーを初期化しようとすると、関数がグローバル変数を壊すことになります。それは非常に悪いことです。

...

コンストラクタnew接頭辞で使用するように設計されている機能です。 newという接頭辞は、関数のプロトタイプに基づいて新しいオブジェクトを作成し、そのオブジェクトを関数implのパラメータにバインドします。 new接頭辞を使用しない場合、新しいオブジェクトは作成されず、thisはグローバルオブジェクトにバインドされます。これは深刻な間違いです。


+0

だから、基本的に 'これ'は、私たちが間違って使用された場合にはグローバルスコープを汚染し、起こることを防ぐために 'チェック'がそこに置かれます。私の質問は、ウィンドウの名前空間に何が問題なのですか?私はこの悪い、しかし決してなぜそうではないかということをとてもよく知る。 – W3Geek

+0

が正しい。 "window"オブジェクトにプロパティを追加することは悪いです。他のフレームワークにもアクセスできる(そしてUSE ITも)のだからです。例えば、 'window.location.href'オブジェクト(現在のURLあなたのブラウザーの)新しいページにナビゲートすることができます。突然あなたの '_'オブジェクトに場所プロパティを追加すると、window.locationプロパティが完全に壊れます。あなた自身の名前空間に制御しているものを置いて、副作用がないことを確認してください。 –

+2

注:グローバルな名前空間に変数を "漏らしている" /stackoverflow.com/questions/5951228/what-is-meant-by-leaking-into-global-scope)。コメントには合っていないと一般的に議論されています:) –

6

return thisであるあなたにチェーンメソッド呼び出しへの機能を提供します。あなたは、_.show().hide()のような本当にクールで役に立つものをいくつかすることができます。 :)

関連する問題