JavaScript秘密花園-scope,namespace,constructor,equality and compparions

116124 ワード

スコープと名前空間
JavaScriptは、ペアの括弧で作成されたコードセグメントをサポートしていますが、ブロックレベルのスコープはサポートされていません.応援するだけで 関数のスコープ
function test() { //      
   
for(var i = 0; i < 10; i++) { //
       
// count
   
}
    console
.log(i); // 10
}
注意: 付与されたステートメントではなく、return式または関数パラメータで{...} 対象となる字面構文解析ではなく、コードセグメントとして解析されます.考えてみれば 自動セミコロンを挿入すると、気づかれにくいエラーが発生する可能性があります.
リセット対象の左括弧とreturnが一行にいないとエラーが発生します.
//    :     undefined
function add(a, b) {
       
return
                a
+ b;
}
console
.log(add(1, 2));
JavaScriptには明示的な名前空間定義がありません.これはすべてのオブジェクトがグローバル共有の名前空間の下に定義されていることを意味します.
変数を参照するたびに、JavaScriptはこの変数が見つかるまで、全体のスコープを上に回ります.グローバルスコープに到達しますが、この変数がまだ見つからない場合は、スローされます.  ReferenceError 異常です
暗黙的なグローバル変数(The bane of global variables)
// script A
foo
= '42';

// script B
var foo = '42'
上の二つのシナリオは効果が違います.スクリプトAはグローバルスコープ内で変数を定義しています.  foo、シナリオBは現在のスコープ内で変数を定義する.  foo上の効果は全然違っています.使わないです.  var 変数を宣言すると暗黙的なグローバル変数が発生します.
//      
var foo = 42;
function test() {
   
//
    foo
= 21;
}
test
();
foo
; // 21
関数で  test 使用しない  var キーワード宣言  foo 変数は外部の同名の変数を上書きします.最初は大きな問題ではないように見えますが、何千何万行ものコードがある場合は使用しません.  var 宣言変数は追跡しにくいバグをもたらします.
//      
var items = [/* some list */];
for(var i = 0; i < 10; i++) {
    subLoop
();
}

function subLoop() {
   
// subLoop
   
for(i = 0; i < 10; i++) { // var
       
// do amazing stuff!
   
}
}
外部ループは最初に起動します.  subLoop あとで止めます.  subLoop グローバル変数を上書きしました.  i二番目に  for ループで使用  var 変数を宣言するとこのようなエラーを回避できます.変数を宣言するときは絶対に忘れないでください.  var キーワードは、外部作用領域に影響を与えることが期待される場合を除きます.
ローカル変数(Local variables)
JavaScriptでは局所変数は二つの方法でしか宣言できません.一つは関数パラメータとして、もう一つは通過です.  var キーワード宣言
//     
var foo = 1;
var bar = 2;
var i = 2;

function test(i) {
   
// test
    i
= 5;

   
var foo = 3;
    bar
= 4;
}
test
(10);
foo 和  i は、関数です  test 内のローカル変数  bar の割り当ては、グローバルスコープ内の同名の変数をカバーします.
変数宣言アップグレード(Hoisting)
JavaScriptは変数宣言をアップグレードします.これは意味します  var 式と  function 宣言は現在のスコープの上部に引き上げられます.
bar();
var bar = function() {};
var someValue = 42;

test
();
function test(data) {
   
if (false) {
        goo
= 1;

   
} else {
       
var goo = 2;
   
}
   
for(var i = 0; i < 100; i++) {
       
var e = data[i];
   
}
}
上のコードは運転前に変換されます.JavaScriptは  var 式と  function 宣言が現在のスコープの上部にアップグレードされました.
// var          
var bar, someValue; // 'undefined'

//
function test(data) {
   
var goo, i, e; // ,
   
if (false) {
        goo
= 1;

   
} else {
        goo
= 2;
   
}
   
for(i = 0; i < 100; i++) {
        e
= data[i];
   
}
}

bar
(); // :TypeError, bar 'undefined'
someValue
= 42; // (hoisting)
bar
= function() {};

test
();
ブロックレベルがない分、それだけではない.  var 表式は循環内から外部に移動され、一部を使用します.  if 表現が分かりにくいです.
元のコードではif 表式はすべての変数を変更したように見えます.  gooは、実際には昇格規則が適用された後、局所変数が修正されている.
ルールを上げる知識がないと、下記のコードが異常に見えます.  ReferenceError
//    SomeImportantThing         
if (!SomeImportantThing) {
   
var SomeImportantThing = {};
}
実際、上のコードは正常に動作します.  var 表式はグローバルスコープの上部にアップグレードされます.
var SomeImportantThing;

// , SomeImportantThing,

//
if (!SomeImportantThing) {
   
SomeImportantThing = {};
}
Nettuts+ウェブサイトでHoistingを紹介する記事がありますが、コードには示唆があります.
//    :   Nettuts+      ,       JavaScript          
var myvar = 'my value';  

(function() {  
        alert
(myvar); // undefined  
       
var myvar = 'local value';  
})();  
名称解析手順(Name reolution order)
JavaScriptの中のすべての作用領域は、グローバルスコープを含めて、特別な名前があります. `this` 現在のオブジェクトを指します.
関数のスコープ内にもデフォルトの変数があります. `アーグメンツ`,ここには関数に伝達するパラメータが含まれています.
例えば、アクセス関数内の  foo 変数の場合、JavaScriptは以下の順序で検索されます.
現在のスコープ内にあるかどうか  var foo の定義関数形式のパラメータが使用されていますか?  foo 名前の関数自体が  foo前のレベルのスコープにさかのぼって、その後 #1 新たに始める注意: カスタム  arguments パラメータは元のものをブロックします.  arguments オブジェクトの作成
名前空間(Namespaces)
グローバルスコープのみに起因する共通のエラーは命名衝突である.JavaScriptでは、これが通過できます. 匿名の包装器 気軽に解決する
(function() {
   
// ( : )

    window
.foo = function() {
       
// ,
   
};

})(); //
匿名関数は 式;したがって、起動可能性のために、それらはまず実行される.
( //             
function() {}
) //
() // ,
いくつかの他の関数式を呼び出す方法があります.例えば、下記の2つの方法は文法が違っていますが、効果は同じです.
//       
+function(){}();
(function(){}());
結論(In conclusion)
匿名の包装器を使って名前空間を作ることをオススメします.このように命名の衝突を防止するだけではなく、プログラムのモジュール化にも有利です.
また、グローバル変数を使うのは悪い習慣と考えられています.このようなコードは、エラーが発生し、高いメンテナンスコストをもたらす傾向があります.
構造関数
JavaScriptの構造関数と他の言語の構造関数は違っています.通過する  new キーワード方式で呼び出された関数はすべて構造関数として考えられています.
コンストラクタの内部で-つまり呼び出された関数の中で-  this 新規作成のオブジェクトを指します.  Objectこの新しく作成したオブジェクトの `prototype` コンストラクタに向けられた  prototype呼び出された関数が明示的でない場合  return 表式を使うと、暗黙的に返されます.  this オブジェクト→新規作成の対象です.
function Foo() {
   
this.bla = 1;
}

Foo.prototype.test = function() {
    console
.log(this.bla);
};

var test = new Foo();
上のコードを  Foo コンストラクタとして呼び出し、新規作成対象の  prototype を選択します  Foo.prototype明示的  return 表式は戻りの結果に影響しますが、戻りの対象に限ります.
function Bar() {
   
return 2;
}
new Bar(); //

// :new Bar() , 2。
// new Bar().constructor === Bar
// ,
// function Bar() {
//    return new Number(2);
// }
// new Bar().constructor === Number


function Test() {
   
this.value = 2;

   
return {
        foo
: 1
   
};
}
new Test(); //
// : , new
// (new Test()).value undefined, (new Test()).foo === 1。
もし  new 欠落した場合、関数は新しく作成したオブジェクトに戻りません.
function Foo() {
   
this.bla = 1; //
}
Foo(); // undefined
上の例では正常に動作する場合もありますが、JavaScriptでは `this` 仕事の原理はここです.  this グローバルオブジェクトを指します.
工場モード(Factores)
使わないために  new キーワード、コンストラクタは値を明示的に返さなければなりません.
function Bar() {
   
var value = 1;
   
return {
        method
: function() {
           
return value;
       
}
   
}
}
Bar.prototype = {
    foo
: function() {}
};

new Bar();
Bar();
上の二つが正しいです  Bar 関数の呼び出しで返した値は全く同じで、新しく作成した所有者  method 属性のオブジェクトが返されますが、ここでは閉じられたパッケージが作成されています.
注意が必要です.new Bar() 戻る対象の原型は変わりません.コンストラクタのプロトタイプは作成したばかりの新しいオブジェクトに向けられます.ここのプロトタイプは  Bar この新しいオブジェクトを返していませんでした.  method 属性のカスタムオブジェクト)
上記の例では、使用または使用しない  new キーワードには機能性の違いがありません.
//    :                Bar        
var bar1 = new Bar();
typeof(bar1.method); // "function"
typeof(bar1.foo); // "undefined"

var bar2 = Bar();
typeof(bar2.method); // "function"
typeof(bar2.foo); // "undefined"
工場パターンによる新規オブジェクト作成(Creating new object victores)
私たちがよく耳にする忠告は使わないことです.  new キーワードを使って関数を呼び出します.これを忘れたらエラーが発生します.
新しいオブジェクトを作成するために、工場法を作成し、方法内で新しいオブジェクトを作成することができます.
function Foo() {
   
var obj = {};
    obj
.value = 'blub';

   
var private = 2;
    obj
.someMethod = function(value) {
       
this.value = value;
   
}

    obj
.getPrivate = function() {
       
return private;
   
}
   
return obj;
}
上記の方式は  new の呼び出し方式は簡単ではありません.プライベート変数を十分に利用することができます.
新たに作成したオブジェクトは原型上の方法を共有できないので、メモリをもっと使うことができます.継承を実現するためには、工場法は、他のオブジェクトからすべての属性をコピーしたり、オブジェクトを新規作成の対象とするプロトタイプが必要です.原型チェーンを放棄するのは、漏れ防止だけです.  new 持ってきた問題は言語そのものの思想とは違うようです.まとめ(In conclusion)
漏れても  new キーワードは問題になるかもしれませんが、プロトタイプチェーンの使用を放棄する口実ではありません.最終的にどのような方法を使うかは、アプリケーションのニーズに応じて、コードを選んでスタイルを書き続けていくことが一番重要です.
同等と比較
JavaScriptは二つの方法で二つの値が等しいかどうかを判断します.
イコールオペレータ(The equals operator)
等しい操作子は2つの等号からなります.==JavaScriptは弱タイプ言語であり、これはオペレータが2つの値を比較するために強制的にタイプ転換することを意味する.
""           ==   "0"           // false
0            ==   ""            // true
0            ==   "0"           // true
false        ==   "false"       // false
false        ==   "0"           // true
false        ==   undefined     // false
false        ==   null          // false
null         ==   undefined     // true
" \t\r
"
   ==   0             // true
上の表は強いタイプの転換を示しています.これも使います.  == プログラムの苦手な習慣の主な原因として広く知られていますが、複雑な変換規則のため、追跡しにくい問題があります.
また、強制型変換は、1つの文字列と比較するために、事前に数字に変換する必要があります.
厳密はオペレータに等しいです.
厳密なイコール操作は3つの等号からなります.===普通のものが操作子に等しいとは思わないが、厳密にはオペレータが強制的なタイプ変換を行うことはない.
""           ===   "0"           // false
0            ===   ""            // false
0            ===   "0"           // false
false        ===   "false"       // false
false        ===   "0"           // false
false        ===   undefined     // false
false        ===   null          // false
null         ===   undefined     // false
" \t\r
"
   ===   0             // false
上記の結果はより明確であり、コードの分析に有利である.二つの操作数のタイプが違ったら、同じではなく、性能の向上にも役立ちます.
比較対象(Compring Object)
とはいえ  == 和  === 操作符は操作符と同じですが、操作数が一つあると動作が違ってきます.
{} === {};                   // false
new String('foo') === 'foo'; // false
new Number(10) === 10;       // false
var foo = {};
foo
=== foo;                 // true
ここでオペレータの比較に等しいのは、値が等しいかどうかではなく、同じアイデンティティに属するかどうかです.つまり、オブジェクトの同じインスタンスだけが等しいと考えられています.これはPythonの中のようです.  is Cのポインタと比較します.
結論(In conclusion)
厳格なものを使用することを強く推奨します.タイプが変換を必要とする場合、言語自体の複雑な強制変換規則を使用するのではなく、比較前に明示的に変換すべきである.