ホームページ  >  記事  >  ウェブフロントエンド  >  Jquery_01_isPlainObject 分析と再構築_JavaScript スキルを超えて

Jquery_01_isPlainObject 分析と再構築_JavaScript スキルを超えて

WBOY
WBOYオリジナル
2016-05-16 18:18:22917ブラウズ

isPlainObject は、Jquery 1.4 以降に提供された新しいメソッドで、オブジェクトが純粋なオブジェクト (「{}」または「新しいオブジェクト」によって作成されたもの) かどうかを判断するために使用されます。

isPlainObject を使用する
まず、「純粋なオブジェクト」とは何かを理解しましょう。「純粋なオブジェクト」とは、Object から構築されたオブジェクトを指します。では、どのオブジェクトが Object から構築されるのか。最初に負荷を負うのは、 new Object() によって構築されたオブジェクトでなければなりません。 注: Object の後の括弧内には何も追加されません。 Object はすべての「クラス」の基礎であるため、いくつかの特別な動作があります。たとえば、new Object(3) が呼び出されるとき、Number 型のオブジェクトが構築されます。 new Object('') は String 型のオブジェクトを構築します。したがって、{} の形式で定義されたオブジェクトも「純粋なオブジェクト」に属します。 '{}' の本質は new Object() ですが、表現が異なります。さて、コードを見てみましょう:

コードをコピーします コードは次のとおりです:

var objStr = new Object('');
alert(objStr.constructor);//String
alert(isPlainObject(objStr));//false
var objNum = new Object(3) ;
alert (objNum.constructor);//Number
alert(isPlainObject(objNum));//false
function Person(){}
var person = new Person(); >alert(isPlainObject(person));//false
var obj01 = new Object();
obj01.name = 'バカの座右の銘';
alert(isPlainObject(obj01));//true
alert( isPlainObject({name:'Motto of Idiot'}));//true

isPlainObject ソース コード分析
次のコードは、Jquery の isPlainObject の完全版です。コメントは非常に詳細です。これ以上言うことはありません。

コードをコピーします コードは次のとおりです。
var toString = Object.prototype.toString,
hasOwnProperty = Object.prototype.hasOwnProperty;
function isPlainObject( obj ) {
// オブジェクトである必要があります。
// IE のため、コンストラクター プロパティの存在も確認する必要があります。 .
//DOM ノードとウィンドウ オブジェクトも通過しないようにします。
//windows オブジェクト:toString.call(window):IE [オブジェクト オブジェクト] FF [オブジェクト ウィンドウ] chrome [ウィンドウ] global] safari [object DOMWindow]
//DOM ノード:toString.call(#div01):IE [object Object] FF [object Window] chrome [object global] safari [object DOMWindow]
//結論: obj.nodeType || obj.setInterval は主に IE ブラウザを判断するために使用されます
//注: 履歴、位置、ナビゲーター、画面の setInterval は未定義です
if ( !obj || toString.call(obj) ! == "[object Object]" || obj.nodeType || obj.setInterval ) {
return false;
}
// 独自のコンストラクター プロパティはオブジェクトでなければなりません
// カスタム オブジェクトを削除します関数 Person(){} などの組み込みオブジェクトの判定 var p = new Person();String,Number
if ( obj.constructor //コンストラクタプロパティがある
&& !hasOwnProperty.call( obj, "constructor" ) //また、コンストラクター プロパティはプロトタイプ チェーンで定義する必要があります
&& !hasOwnProperty.call(obj.constructor.prototype, "isPrototypeOf")//プロトタイプには isPrototypeOf メソッドがあります。通常、オブジェクトのプロトタイプ内でのみこのメソッドのみ
) {
return false
}
// 独自のプロパティが最初に列挙されるため、高速化するために、
// 最後のプロパティが
//複雑なクラス構造の場合、継承がある場合...
/*
//単純なテスト
function Animal(name){
}
関数 人(名前,年齢){
Animal.call(この,名前);
この.年齢 = 年齢;
}
var p = 新しい人('jxl', 20);
for(key in p){
alert(hasOwnProperty.call( p, key ))//true , false
}
*/
var key; for ( key in obj ) {}
return key === unknown || hasOwnProperty.call( obj, key );
}

質問する
個人的にはこの実装はより複雑で、バグがあると感じます。
単純なバグ、履歴、位置、ナビゲーター、画面は、isPlainObject の検出を通じて連続して true を返すことができます。
私の解決策を見てみましょう (バグを修正し、単純化します):



コードをコピーします コードは次のとおりです。 function isPlainObject(obj){
if(obj&&Object.prototype. toString.call(obj)= ==="[object オブジェクト]"&&obj.constructor===Object &&!hasOwnProperty.call(obj, "constructor")){
var key; obj ) {}
return key === unknown || hasOwnProperty.call( obj, key );
return
}


もありますバグ、そしてそれは解決不可能なバグです:



コードをコピー
コードは次のとおりです:

function m(){};
m.prototype.constructor=Object; //
obj=new m; //true

同じロジックを持つ別のコード:

コードをコピーします コードは次のとおりです:
function m(){};
m.prototype = {};
alert(isPlainObject(obj));

この答えは解決できません!
答えは解けません
この問題は簡単に解けると思っていましたが、深く掘り下げてみると解けない問題であることが分かりました。その理由は次のとおりです。



コードをコピー コードは次のとおりです。 function Person( ){};
person.prototype.constructor=Object;
var person=new Person;


の現在の状態を見てみましょう。
person とその構造 関数 person への唯一の接続は、そのプロトタイプ チェーン内のコンストラクター属性です。それが「純粋なオブジェクト」であるかどうかを判断するときは、主にオブジェクト インスタンスのコンストラクターに基づいて判断されます。図でわかるように、これを Object に指定すると、コード内では person と person に関係がなくなります。だからこそ、型判定に問題が生じるのです。
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。