Javascriptの罠大集合

6234 ワード


スコープ
ブロックのスコープがありません
前の観点に注目したかもしれません.javascriptにはブロックスコープの概念がなく、関数スコープだけがあります.下のコードを試してもいいです.

	for(var i=0; i<10; i++) {
    console.log(i);
}
var i;
console.log(i); // 10
iがforサイクルに定義されると、ループを終了した後、その人はこのロールドメインに保持されるので、最終的に呼び出しconsolie.logは10を出力した.この問題を避けるためにJSLint警告があります.すべての変数を関数の先頭に強制的に定義します.私たちは直ちに実行するfunctionを書くことによって、役割領域を作成することができます.

	(function (){
    for(var i=0; i<10; i++) {
        console.log(i);
    }
}());
var i;
console.log(i); // undefined
内部関数の前に変数を宣言して、この変数を関数で再宣言すると、次のような奇妙な問題が発生します.

	var x = 3;
(function (){
    console.log(x + 2); // 5
    x = 0; //No var declaration
}());
しかし、内部関数でx変数を再宣言すると、奇妙な問題が発生します.

	var x = 3;
(function (){
    console.log(x + 2); //NaN - x is not defined
    var x = 0; //var declaration
}());
これは関数でx変数が再定義されたためで、翻訳プログラムが関数の上部にvar表現を移動したことを示しています.

	var x = 3;
(function (){
    var x;
    console.log(x + 2); //NaN - x is not defined
    x = 0;
}());
これは本当に意味があります.
グローバル変数
Javascriptは全体的な役割領域を持っています.あなたのコードのために名前空間を作る時は慎重にしてください.大域変数は、それらにアクセスすると、動作時に各作用領域を介してそれらを見つけるまで確立しなければならないので、アプリケーションに性能問題を追加します.彼らは意図的または意図的にアクセスされたり、修正されたりします.これはもう一つの深刻な問題を引き起こします.もし悪意のある人があなたのページでコードを実行する方法を見つけたら、彼らはグローバル変数を修正することで、あなたのアプリケーションを混乱させやすいです.経験の乏しい開発者は、無意識のうちに変数をグローバルスコープに追加していきます.この記事を通じて、このように何か意外なことがあるかをお伝えします.
下記のコードを見たことがありますが、2つの値が等しいローカル変数を宣言しようとします.

	var a = b = 3;
これは非常に正確にa=3とb=3を得たが、aは局所作用領域においてbはグローバルスコープにおいて、b=3は先に実行され、グローバル操作の結果、3はまた局所変数aに割り当てられる.
下記のコードは2つの値が3の変数であることを宣言しています.

	var a = 3,
b = a;
”this”と内部関数
「this」キーワードは通常、現在実行中の関数のオブジェクトを指しますが、関数がオブジェクトに呼び出されていない場合、例えば内部関数では「this」はグローバルオブジェクト(window)に設定されます.

	var obj = {
    doSomething: function () {
        var a = "bob";
        console.log(this); //        
        (function () {
            console.log(this); // window - "this" is reset
            console.log(a); // "bob" - still in scope
        }());
    }
};
obj.doSomething();
雑の部
データは存在しません.「null」と「undefined」
データが存在しないことを示す二つのオブジェクトの状態があります.nullとundefined.これは他のプログラミング言語、例えばC〹から回転するプログラマーをかなり混乱させます.次のコードがtrueに戻ることを期待するかもしれません.

	var a;
a === null; //false
a === undefined; //true
「a」は実際にundefinedです.(ダブルイコール==でnullと比較するとtrueの結果が出ますが、これは表面的には正しいように見える他のエラーです.)
変数が本当に存在するかどうかを確認したいなら、ダブルイコールでは判断できません.次の方法を使います.

	if(a !== null && a !== undefined) {
    ...
}
は、nullとundefinedがfalseである以上、そうしてもいいです.

	if(a) {
    ...
}
もちろん、0はfalseで、空の文字列もです.その中の一つがaの正確な値であれば、前者を使います.その比較的短い方法は、object、arrays、そしてbollansのタイプを比較するのに適しています.
再定義undefined
非常に正確です.undefinedを再定義できます.これは保留されていないためです.

	undefined = "surprise!";
しかし、undefined変数に値を割り当てるか、または「void」を使うことで値を取ります.

	undefined = void 0;
これはなぜjqueryスクリプトライブラリの第一行がこう書かれたのですか?

	(function ( window, undefined ) {
    ... // jQuery library!
}(window));
この関数が呼び出された時には、第二のパラメータ「undefined」が実際にundefinedであることを確認しながら、一つのパラメータが入ってきます.
ちなみに、nullを再定義することはできません.しかし、NaN、Infinity、コンストラクションの内蔵タイプを再定義できます.このように試してみてもいいです.

	Array = function (){ alert("hello!"); }
var a = new Array();
もちろん、Arayはどこでもテキスト文法で宣言できます.
任意のセミコロン
Javascriptコードの中でセミコロンが選択されていますので、初心者はコードを書くのが簡単です.しかし、セミコロンを無視すれば誰にも便利にならないです.結果として、解釈器が間違っている時は、どのセミコロンが書き漏らしたのかを追跡して推測してみなければなりません.
ここには古典的な例があります.

	return
{
    a: "hello"
};
上のコードは対象に戻りません.undefinedに戻りました.しかし、エラーなく投げられました.リターン文の後に自動的にセミコロンが追加されています.他のコードは全部正しいです.しかし、何も実行しないことは、javascriptでは左括弧がこの行に続いて改行してはいけないことを証明しています.これはプログラムのスタイルだけではありません.の問題です.次のコードはaの属性のオブジェクトに正しく戻ります.

	return {
    a: "hello"
};
NaN
NaNのタイプは…Numberです.

	typeof NaN === "number" //true
またNaNと何の比較もfalseです.

	NaN === NaN; // false
NaNの間は比較できないので、一つの数字がNaNかどうかを唯一判断する方法はisNaNメソッドを呼び出すことです.
もう一つの態様からは、関数isFiniteを使用してもよく、そのうちの一つの動作数がNaNまたはInFinityであるときにfalseを返す.
アーグメンントオブジェクト
一つの関数では、argmentsオブジェクトを参照して、入力されたパラメータリストを遍歴することができます.最初の不思議なところは、このオブジェクトはArayではなく、Arayのようなオブジェクトです.(0-length-1の間の値があります.).arrayに変換するために、arrayのsplice関数に対応するary配列を作成することができます.

	(function(){
console.log(arguments instanceof Array); // false
var argsArray = Array.prototype.slice.call(arguments);
console.log(argsArray instanceof Array); // true
}());
二つ目の変なところは、関数の署名に明示的なargmentsパラメータがある場合、それらは再割り当てされ、argmentsオブジェクトも変更されます.これは、argmentsオブジェクトが変数そのものを指すことを示しています.argmentsオブジェクトを利用してそれらの初期値を与えることはできません.

	(function(a){
    alert(arguments[0]); //1
    a = 2;
    alert(arguments[0]); //2
}(1));