Aray,Aray Costructor,for in loop,typeof,instance Of

7791 ワード

注意:JavaScriptの配列は関連配列ではありません.JavaScriptでは、キーの対応関係を対象のみに管理します.ただし、関連配列は順序を保持し、対象はそうではない.
for inサイクルはプロトタイプチェーン上のすべての属性を列挙しますので、これらの属性をフィルタリングする唯一の方法は`hasOwnProperty`関数を使うので、普通のforサイクルより何倍も遅くなります.
巡回(Iteration)
エルゴード配列の最適な性能を達成するために、古典的なforサイクルの使用を推奨します.
 
  
var list = [1, 2, 3, 4, 5, ...... 100000000];
for(var i = 0, l = list.length; i < l; i++) {
console.log(list[i]);
}
上のコードには、配列の長さをl=list.lengthでキャッシュする処理があります.
lengthは配列の属性の一つであるが、ループ毎にアクセスするとパフォーマンスオーバーヘッドがある.最新のJavaScriptエンジンはこの点で最適化されたかもしれませんが、私たちは自分のコードがこれらの一番近いエンジンの上で実行されるかどうかを保証できません.
実際には、キャッシュ配列長を使用しない方がキャッシュバージョンよりもかなり遅いです.
`length`属性(The`length`property)
length属性のgetter方式は単純に配列の長さを返しますが、setter方式は配列を切断します.
 
  
var foo = [1, 2, 3, 4, 5, 6];
foo.length = 3;
foo; // [1, 2, 3]

foo.length = 6;
foo; // [1, 2, 3]
Firebugでこの時のfooの値を見ると、「1、2、3、undefined、undefined、undefined」です.しかし、この結果は正確ではありません.Chromeのコンソールでfooの結果を見ると、「1、2、3」はJavaScriptでundefinedは変数ではないので、キーワードに注意してください.したがって、上の二つの結果の意味は全く違っています.
//訳者注:検証のために、私達は下記のコードを実行して、番号5がfooに存在するかどうかを確認します.
5 in foo;//FirebugでもChromeでもfalseに戻ります.
foo[5]=undefined
5 in foo;//FirebugでもChromeでもtrueに戻ります.
lengthのためのより小さな値を設定すると、配列は切断されますが、length属性値を増加させると、配列に影響はありません.
結論(In conclusion)
より良い性能のためには、通常のforループを使用して、配列のlength属性をキャッシュすることを推奨します.for inエルゴード配列を使用することは良くないコード習慣と考えられ、エラーや性能問題を引き起こす傾向がある.
Arayコンストラクタ
Arayのコンストラクタはパラメータをどう処理するかがあいまいなので、配列の字面文法-[]-を使って配列を作成することを常に推奨しています.
[1,2,3]///結果:[1,2,3]
new Aray(1,2,3)//結果:[1,2,3]
[3]///結果:[3]
new Aray(3)///結果:[]
new Aray('3')//結果:['3']
ここのあいまいさとは、配列の2つのコンストラクション文法であるvar arr 1=new Aray(arryLength)のことです.var arr 2=new Aray(element 0,element 1,…,element N)
//訳者注:これで次のコードが迷うことになります.
new Aray(3,4,5)//結果:[3,4,5]
new Aray(3)//結果:[]この配列の長さは3
一つのパラメータだけがコンストラクタに渡されますので、このパラメータは数字です.コンストラクタはlength属性を返します.このパラメータの空配列を設定します.特に注意が必要なのは、この時にはlength属性だけが設定されていて、本当の配列は生成されていません.Firebugでは、「undefined、undefined、undefined」というのが見えますが、これは間違っています.前の節に詳しい分析があります.
var arr=new Aray(3);
arr[1]//undefined
1 in arr;//false、配列はまだ生成されていません.
配列長属性の設定に優先するこの方法は、循環文字列が必要な場合など、数種類の場合にのみ有用です.
new Aray(count+1).jun(strigToRepeat);
//訳者注:new Aray(3).join('啱')は「菗33751;萶」に戻ります.
結論(In conclusion)
配列構造関数を使って新しい配列を作成することは、できるだけ避けなければなりません.配列の文面文法を推奨します.それらはより短く、簡潔であり、したがって、コードの可読性を高める.
for inサイクル
in操作子と同じように、for inはオブジェクト属性を検索する際に、プロトタイプチェーン上のすべての属性を巡回します.
注意:for inサイクルはそれらのenumerableを遍歴しないでfalseの属性に設定します.配列のlength属性のようなものです.
 
  
// Object.prototype
Object.prototype.bar = 1;

var foo = {moo: 2};
for(var i in foo) {
console.log(i); // :bar moo
}
for in自身の行動を変えることができないので、循環体に現れたくない属性をフィルタリングする必要があります.これはObject.prototypeの原型にある‘hasOwnProperty`関数によって完成できます.
for inは常にプロトタイプチェーン全体を巡回しますので、対象の継承レベルが深すぎると性能に影響します.
‘ハスOwnProperty`フィルタリング(Using`hasOwnProperty`for filtering)を使用します.
 
  
// foo
for(var i in foo) {
if (foo.hasOwnProperty(i)) {
console.log(i);
}
}
このバージョンのコードは唯一正しい書き方です.私たちはハスOwnPropertyを使っていますので、今回はmooだけを出力します.hasOwnPropertyを使用しないと、このコードは元のオブジェクトのプロトタイプ(例えばObject.prototype)が拡張されているときにエラーが発生します.
広く使われているクラスのProttypeは、元のJavaScriptオブジェクトを拡張します.したがって、このクラスがページに含まれている場合は、ハスOwnPropertyフィルタを使わないfor inサイクルが問題になります.
ベストプラクティス(Best practices)
いつもハスOwnPropertyを使うことをオススメします.コードが実行される環境を仮定しないでください.元のオブジェクトが拡張されていると仮定しないでください.
typeof操作符
typeofオペレータは、JavaScriptの中で最大の設計欠陥かもしれません.それらから所望の結果が得られないからです.
instance ofにはまだ少数のアプリケーションシーンがありますが、typeofは実際のアプリケーションしかありません.このアプリケーションは対象の種類を確認するのではありません.
注意:typeofは、typeof(obj)などの関数の構文のようにも呼び出されますが、これは関数として呼び出されません.二つの小かっこは一つの表式の値だけを計算します.この戻り値はtypeofオペレータの操作数とします.実際にはtypeofという関数は存在しません.
JavaScriptタイプテーブル(The JavaScript typeテーブル)
Value Class Type
-----------------------
「foo」String string
new String(「foo」)String oject
1.2 Number number
new Number(1.2)Number object
true Boolean bolean
new Boolean(true)Boolean object
new Date()Date object
new Error()Error object
[1,2,3]Aray object
new Aray(1,2,3)Aray object
new Function(")Function function
//abc/g RegExp object(function in Nitro/V 8)
new RegExp(「meow」)RegExp oject(function in Nitro/V 8)
{}Object object
new Object()Object object
上の表では、Typeの列はtypeofオペレータの演算結果を表しています.この値はほとんどの場合「object」に戻ります.
クラスは対象の内部属性[クラス]の値を一列に表します.
JavaScript標準文書で定義されています.[クラス]の値は次の文字列の中の一つです.Agments、Aray、Boolean、Date、Error、Function、JSON、Math、Number、Object、RegExp、String.
対象の[クラス]を取得するためには、Object.prototypeに定義された方法toStringを使用する必要があります.
オブジェクトのクラス定義(The Class of an object)
JavaScript標準文書は、Object.prototype.tostringを使用して値を取得する方法を提供しています.
 
  
function is(type, obj) {
var clas = Object.prototype.toString.call(obj).slice(8, -1);
return obj !== undefined && obj !== null && clas === type;
}

is('String', 'test'); // true
is('String', new String('test')); // true
上記の例では、Object.prototype.toString方法が呼び出され、thisは[クラス]値を取得する必要があるオブジェクトに設定されている.
Object.prototype.toStringは標準的な書式文字列を返しますので、上記の例はsliceで指定された位置の文字列を切り取ります.
 
  
Object.prototype.toString.call([]) // "[object Array]"
Object.prototype.toString.call({}) // "[object Object]"
Object.prototype.toString.call(2) // "[object Number]"
ES 5ヒント:ECMAScript 5では、簡単にするために、nullとundefinedにObject.prototype.toString方法を呼び出して、その戻り値はObjectからNullとUdefinedになりました.
このような変化はIE 8とFirefox 4の違いを見ることができます.
 
  
// IE8
Object.prototype.toString.call(null) // "[object Object]"
Object.prototype.toString.call(undefined) // "[object Object]"

// Firefox 4
Object.prototype.toString.call(null) // "[object Null]"
Object.prototype.toString.call(undefined) // "[object Undefined]"
(Testing for undefined variables)
typeof foo !== 'undefined'
上のコードはfooが定義されているかどうかを検出します.定義なしでそのまま使用するとReferenceErrの異常を招きます.これはtypeofの唯一の役に立つところです.
結論(In conclusion)
オブジェクトのタイプを検出するために、Object.prototype.toStringメソッドを使用することを強く推奨します.これは唯一の頼りになる方法だからです.上の表に示すように、typeofのいくつかの戻り値は標準ドキュメントでは定義されていないため、異なるエンジン実装が可能です.
変数が既に定義されているかどうかを検出するためには、typeofオペレータの使用はできるだけ避けなければなりません.
instance ofオペレータ
instance ofオペレータは、2つの操作数の構造関数を比較するために使用されます.カスタムオブジェクトを比較するときのみ意味があります.内蔵タイプを比較するのに使うと、typeofオペレータと同じようにあまり役に立ちません.
カスタムオブジェクトの比較(Compring custom Object)
 
  
function Foo() {}
function Bar() {}
Bar.prototype = new Foo();

new Bar() instanceof Bar; // true
new Bar() instanceof Foo; // true

// Bar.prototype Foo , Foo
Bar.prototype = Foo;
new Bar() instanceof Foo; // false
`instanceof` (Using `instanceof` with native types)
new String('foo') instanceof String; // true
new String('foo') instanceof Object; // true

'foo' instanceof String; // false
'foo' instanceof Object; // false
ちょっと注意したいのですが、instance ofはJavaScriptのコンテキストに属するオブジェクト(例えば、ブラウザ内の異なるドキュメント構造)を比較する際にエラーが発生します.それらの構造関数は同じオブジェクトではないためです.
結論(In conclusion)
instance ofオペレータは、同じJavaScriptコンテキストからのカスタムオブジェクトを比較するためにのみ使用されるべきである.`typeof`操作符のように、他のどのような使い方も避けられます.