« 『あちら』側の技術者や『あちら』側を理解している技術者に『こちら』側で遭遇できるか | メイン | RFCの印刷を支援するBookmarklet »

Library内のhasOwnProperty使用に対する補足説明

はてなブックマークで『ObjectをJSONへ変換するJavaScript Library』に対して次の様な突っ込みが入っていた。
json化するのにhasOwnPropertyじゃなくてfunctionかそうでないかくらいで十分な気がする
確かに説明不足な感は否めないので、補足。Functionオブジェクトはswitchの『default:』に振り分けられ、『case Object:』内は実行されない。では、『hasOwnProperty』は何のためにあるのか。著名なLibraryである『Prototype.js』等で、javascriptのnativeのObjectを拡張している。有用な機能を拡張しているため、便利ではあるが、手放しには喜べない。例えば、次の様な処理を考える。
//[for in]処理
var obj={"a":"apple","b":"box","c":"cat"};
var res="";
for(var key in obj){
    res+=key+":"+obj[key]+"¥n";
}
alert(res);

/*
以下のように表示される。
a:apple
b:box
c:cat
*/
通常では上記方法で問題はないが、Objectを拡張している場合は問題となる。
//Objectの拡張
Object.prototype.f1=function(){return "function1";}
Object.f2=function(){return "function2";}
Object.prototype.v1="value1";
Object.v2="value2";

//[for in]処理
var obj={"a":"apple","b":"box","c":"cat"};
var res="";
for(var key in obj){
    res+=key+":"+obj[key]+"¥n";
}
alert(res);

/*
以下のように表示される。
a:apple
b:box
c:cat
f1:function(){
    return "function1";
}
v1:value1
*/
つまり、prototypeに拡張したクラスメソッドやクラスフィールドまで拾ってきてしまうのである(正確にはJavaScriptはクラスとは言わない)。『for in』処理はさほどマイナーな処理ではないため、既存システムのカスタマイズ時に『Prototype.js』を安易に導入すると、既存処理と衝突する可能性がある。これを一部では『Object汚染』と表現する。これを回避するために『hasOwnProperty』を使用しているのである。
//Objectの拡張
Object.prototype.f1=function(){return "function1";}
Object.f2=function(){return "function2";}
Object.prototype.v1="value1";
Object.v2="value2";

//[for in]処理
var obj={"a":"apple","b":"box","c":"cat"};
var res="";
for(var key in obj){
    //Object汚染回避
    if(obj.hasOwnProperty(key)){
        res+=key+":"+obj[key]+"¥n";
    }
}
alert(res);

/*
以下のように表示される。
a:apple
b:box
c:cat
*/
前述のLibraryのhasOwnPropertyは、この問題を回避するためのものであり、Functionの判定処理ではない。

トラックバック

このエントリーのトラックバックURL:
http://www.kanasansoft.com/cgi/mt/mt-tb.cgi/34

コメントを投稿

(いままで、ここでコメントしたことがないときは、コメントを表示する前にこのブログのオーナーの承認が必要になることがあります。承認されるまではコメントは表示されません。そのときはしばらく待ってください。)

Google