この神話を破壊します。
JQueryロジック
jQuery.eachメソッドのロジックを見てみましょう。 入力では、最初のパラメーターのタイプ、より正確には、オブジェクトであるかどうかがチェックされます。
length = obj.length, isObj = length === undefined || jQuery.isFunction( obj );
lengthプロパティがない場合、これはObjectです。 そして、長さがそうであれば、これは配列です。
非常に普遍的なアプローチではありません。 見てみましょう。
いくつかのプロパティを持つオブジェクト「Obj」を作成しましょう。その中に、書き込みと長さを指定します。
var Obj = { name: "test", size: 2, length: 5 };
それをjQuery.eachに渡しましょう:
$.each( Obj, function() { console.log( this, arguments ); } );
実行結果:
Window [0, undefined] Window [1, undefined] Window [2, undefined] Window [3, undefined] Window [4, undefined]
失敗。 jQueryはそれを配列として定義し、forループにダミーの長さプロパティを使用しました。
しかし、この問題を回避する方法は? いくつかのアイデアがありました。 これから徐々にそれらを検証し、最も適切で普遍的な実装に到達します。
方法1:Typeof
この方法は私たちには適していない、なぜなら そして、オブジェクトと配列の両方のtypeofは「オブジェクト」です。 さらに、文字列と数値を区別する必要がある場合、new演算子を使用して作成された場合、再び「オブジェクト」を取得します。
方法2:instanceof
ここで私は間違っていました。 帽子だと思って、適切な方法が見つかりました。
しかし、次の落とし穴を避けることはできませんでした。
var a = {}; a instanceof Object; => true var b = []; b instanceof Array; => true var c = 5; c instanceof Number; => false var d = ""; d instanceof String; => false
オブジェクトと配列に問題はありません。 ただし、instanceofは、new演算子を使用して作成された場合にのみ、数字と文字列を処理します。 どうぞ
方法3:コンストラクター
これが作業方法です。 コンストラクターの比較。
var a = {}; a.constructor === Object; => true var b = []; b.constructor === Array; => true var c = 5; c.constructor === Number; => true var d = ""; d.constructor === String; => true
全体像については、結果を比較する表:
方法 | タイプ | instanceof | コンストラクター |
---|---|---|---|
新しい配列() | 「オブジェクト」 | 本当 | 本当 |
[] | 「オブジェクト」 | 本当 | 本当 |
新しいオブジェクト() | 「オブジェクト」 | 本当 | 本当 |
{} | 「オブジェクト」 | 本当 | 本当 |
新しい文字列() | 「オブジェクト」 | 本当 | 本当 |
「」 | 「ストリング」 | 偽 | 本当 |
新しい番号() | 「オブジェクト」 | 本当 | 本当 |
5 | 「番号」 | 偽 | 本当 |
結論:
おそらく、各メソッドは次のようになります(デモンストレーションのためにargsの一部を取りませんでした)。
each: function( obj, callback, args ) { var name, i = 0, length = obj.length, isObj = obj.constructor === Object, isArray = obj.constructor === Array || obj.constructor === String; if ( isObj ) { for ( name in obj ) { if ( callback.call( obj[ name ], name, obj[ name ] ) === false ) { break; } } } else if ( isArray ) { for ( ; i < length; ) { if ( callback.call( obj[ i ], i, obj[ i++ ] ) === false ) { break; } } } }
ご清聴ありがとうございました。
更新しました。
有益なコメントをありがとう。 この記事の目的は、まず、JavaScriptでデータ型を区別する方法を示すことであり、jQueryのバグを明らかにすることではありません。
「toString」を使用する方法の方が適していることに同意します。 すぐに記事を修正します。 フィードバックをありがとう。 このトピックは私にとって興味深いので、最良の方法も見つけたいと思います。