The Good Parts 3章 オブジェクト
2010/08/12(木) 21:46 Javascript親記事へこのエントリーをはてなブックマークに追加

コードが出てくるのはこの辺からということでここから開始。

3.1 オブジェクトリテラル

特にいうことない。
わざわざfirst-nameのようなブラケット表記法でないとアクセスできないようなプロパティの書き方をしている。 via Member Operators - MDC
var empty = {};
var stooge = {
    "first-name": "Jerome",
    "last-name" : "Howard"
}

var flight = {
    airline : "OCeanic",
    number : 815,
    departure : {
        IATA : "SYD",
        time : "2004-09-22 14:55",
        city : "sydney" // ここに,を入れるとIEはエラー
    },
    arrival: {
        IATA : "LAX",
        time : "2004-09-23 10:42",
        city : "Los Angeles"
    } // ここも同様に,はいれない
}
// 尻カンマってやつです
// http://blog.livedoor.jp/dankogai/archives/50893888.html

3.2 値の取得

flight.equipmentが定義されてないのに、flight.equipment.modelへアクセスするとTypeErrorになるので、&&演算子を使って不要なエラーを出さないようする。
flight.equipment && flight.equipment.model;
// よくあるのがオブジェクトのプロパティにアクセスするとき。
// 処理的にもこうした方が早い。短絡評価という名前だった気がする
if(obj && obj.prop){
    // 何か
}
もっと踏み込んだ例外回避
__proto__:null のススメ - ’ellaneous

3.3 値の更新

参照したものに=で代入できるよねって話。(当たり前か
もっと詳しくやると_defineSetter__ と __defineGetter__ ( https://developer.mozilla.org/ja/Core_JavaScript_1.5_Reference/Global_Objects/Object/defineGetter , https://developer.mozilla.org/ja/Core_JavaScript_1.5_Reference/Global_Objects/Object/defineSetter ) というものでどういう風に返すのか、代入するのかを決められる。(普通使う事ない)
var empty = {};
var stooge = {
    "first-name": "Jerome",
    "last-name" : "Howard"
}

var flight = {
    airline : "OCeanic",
    number : 815,
    departure : {
        IATA : "SYD",
        time : "2004-09-22 14:55",
        city : "sydney"
    },
    arrival: {
        IATA : "LAX",
        time : "2004-09-23 10:42",
        city : "Los Angeles"
    }
}

var middle = stooge["middle-name"] || "none";
var status = flight.status || "unknown";
stooge["middle-name"] = "Jerome";
stooge.nickname = "curly";
flight.equipment = {
    model:"boeiing 777"
};
flight.status = "overdue";

3.4 参照

オブジェクトを代入した場合は参照になるよって話。
// 3-4.js 参照
var stooge = {
    "first-name": "Jerome",
    "last-name" : "Howard"
}
var x = stooge;
x.nickname = "Curly";
p(stooge.nickname);// "Curly"
同じオブジェクトを参照してプロパティを追加した場合。
var a= {}, b={} , c= {};// 正直これいらない
a=b=c={}; // 同じ{}を参照している。
a.prop = "追加";
console.log(b); // bも同じオブジェクトを指す //=> {prop : "追加"}
以下のコードでbにはaというプロパティがないのはなんで?
var a = b = {};
a = {a: 'a'};
p(b.a); // undefinedになってしまう
print(b.a); // undefined
これは二行目で新たなオブジェクトを作り入れているから
var a = b = {};
a = {a: 'a'};// ここでa.a = "a";を期待するが、
// 実際は{a: 'a'}というオブジェクトを作りaに代入している。
p(b.a);  // undefined
// => もっとかみ砕くと
var b = a = {};
a = {};
a.a = "a";
print(b.a); // undefined

3.5 プロトタイプ

いわゆるプロトタイプ的継承の話。
404 Blog Not Found:javascript - プロトタイプ的継承
あるオブジェクトにプロパティが無かったら、そのオブジェクトのプロトタイプを遡っていき、最終的にはJavaScriptに元々あるObject関数にたどり着いて、そこにもプロパティが無かったらundefinedを返す。(このプロトタイプチェーンをたどる仕組みを「委譲」とかいうらしいけど聞いたことない)

プロトタイプチェーンの話は今日の知っ得まる得 ECMAScript - oogattaの勉強日記がとてもいい。(prototypeの動きが分かってから見るといい)
// 3-5.js プロトタイプ
var stooge = {
    "first-name": "Jerome",
    "last-name" : "Howard"
}
// Object.createというメソッドを作る
if (typeof Object.create !== 'function') {
    Object.create = function (o) {
        function F() {}
        F.prototype = o;
        return new F();
    };
}
var another_stooge = Object.create(stooge);// stoogeを継承
another_stooge["first-name"] = "Harry";
another_stooge["middle-name"] = "Moses";
another_stooge.nickname = "Moe";
p(stooge["first-name"]); // Jerome 変化してない
stooge.profession = "actor";
p(another_stooge.profession); // actor 
another_stooge.profession; は無いため、プロトタイプチェーンをたどり、
another_stooge.__proto__.profession (__proto__はプロトタイプをたどるプロパティ)を参照してanother_stooge.__proto__.professionはstooge.professionなので、stooge.professionの値(actor)が返る
another_stooge -> stooge -> Object
another_stoogeがstoogeのプロパティを継承してるように見えるので、よくプロトタイプ継承とか言われる。

3.6 リフレクション

はてな「JavaScript で学ぶ イベントドリブン」のメモ - prog*sigでもでてきたけど、typeofの判定結果でfunctionとobjectとか判定し難いものも合ったりする。
Arrayの判定方法にはObject.prototype.toStringを使うのが一般的らしい
typeof flight.toStringだとプロトタイプチェーンを辿ってしまうので、そのオブジェクトが持っているプロパティかどうかを判定したい場合はhasOwnPropertyを使用する。

3.7 プロパティの列挙

for...inでの列挙はプロトタイプチェーンを辿るのでプロトタイプ拡張してるとマズいものが列挙されてしまう。
そのためhasOwnPropertyとセットで使うのをよく見る。
for (var name in another_stooge) {
    if (another_stooge.hasOwnProperty(name)) {
        console.log(name, ':', another_stooge[name]);
    }
}
hasOwnPropertyは何か使いづらいので、使わなくても良い方法や汚染を回避する方法などを取ることがよくある。

3.8 プロパティの削除

deleteの使い方。
複数合ったものをdeleteするともう片方が見えてくる。
あまり使わないのでどっかの人もハマってる感じがした

3.9 グローバル領域の利用を減らす

グローバル名前空間はできるだけ減らす。
JavaScript Cookbookでもよく出てきた内容で、JavaScriptに限らずグローバル変数の使いすぎは止めときましょう。
3章はプロトタイプの登場の巻

名前:  非公開コメント   

  • TB-URL  http://efcl.info/adiary/060/tb/