SlideShare a Scribd company logo
ECMAScript 5 時代の
オブジェクト・プロトタイプ継承入門



       id:nobuoka
         (@nobuoka)

     2012-11-29 Kyoto.js #2
自己紹介と概要
●   id:nobuoka - はてなブックマークチーム
●   Java, JavaScript, Ruby あたりの言語が好き
●   仕事では Perl と JavaScript

●   今日は初心者向けの話
    –   オブジェクト?
    –   プロトタイプ継承?
●
    ECMA-262 5.1th ベース
ECMAScript とは?
●   JavaScript の言語コア部分に相当する言語
●   ECMA International による仕様 : ECMA-262
●   最新のバージョンは 5.1
    –   ECMAScript Language Specification (5.1th)
    –   古い IE では 5.1 の機能が使えなかったりする
    –   プロトタイプ継承などを 5.1 的に説明してみる
        (本資料中の節番号は
         ECMA-262 5.1th の節)
JavaScript におけるオブジェクト
●   値の一種 : Object 型の値
●   Object 型の他には String 型とか Number 型とか
●   JavaScript には C++ や Smalltalk のようなクラスはな
    い
●   オブジェクトリテラルによってやコンストラクタによってな
    ど、様々な方法で生成される

var obj1 = {
    name : “Hanako”,
    age : 18
};
var obj2 = new Object();
オブジェクトはプロパティの集合体
●   “An Object is a collection of properties.” (8.6 節)
●   プロパティ : 名前と値の結合物 (association)
    –   Named data property : プロパティといえばこれ
    –   Named accessor property
    –   Internal property : 仕様説明のための内部的なもの

           var obj1 = {
               name : “Hanako”,
               age : 18             名前は age, 値は数値
           };                       18 であるプロパティ
オブジェクトの同値性 (概念上の話)
●   もっているプロパティの名前が全て同じで、名前に対応す
    る値も同じ、という 2 つのオブジェクトがあっても、それら
    のオブジェクトは同じ値ではない
●   JavaScript ではオブジェクトそのものが値だから (同じオ
    ブジェクトでなければ同じ値ではない)

// 2 つのオブジェクトは同じ値ではない
{ p: “y” } !== { p: “y” }

                   当たり前といえば当たり前。
                   C から来た人などは戸惑うかも。
オブジェクトの同値性 (概念上の話)
●   引数として渡されたオブジェクトに対する操作は、
    もとのオブジェクトに影響する (同じ値なので当然)
// 引数として渡されたオブジェクトの val プロパティの
// 値をインクリメントする関数
function incVal(o) { o.val += 1 }
var obj = { val: 10 };
incVal(obj); // incVal 呼び出し後の obj.val の値は 11

『JavaScript 第 5 版』 では 「参照によるデータ操作」 など
と説明されている。 実践的にはそれでいいが、仕様を読むに
はここで説明したこと (オブジェクトそのものが値) の理解が必要。
Accessor property
●   いわゆる setter / getter
●   最近のブラウザなら (IE10 含め) 基本的に使える

var obj = {
    _val: 0,
    get val() { return this._val },
    set val(v) { this._val = v }
};
obj.val = obj.val + 10;
Property Attributes (8.6.1 節)
●   プロパティの属性
    – [[Value]] : データプロパティの値
    – [[Writable]] : 書き換えできるか
    – [[Set]], [[Get]] : setter / getter
    – [[Configurable]] : 変更できるかどうか
    – [[Enumerable]] : for-in ループで列挙されるかどうか
●   Object.getOwnPropertyDescriptor (15.2.3.3 節)
Object.defineProperty (15.2.3.6 節)
●   Property Attributes を指定してプロパティを定義
●   Object.defineProperties もあるよ (15.2.3.7 節)
var obj = {};
Object.defineProperty(obj, “newProp”, {
    value: 200,
    writable: false
});
obj.newProp = 10; // writable : false なので書きこまれない

Object.defineProperties(obj, {
    newProp2: {
      get: function () { return 200 }
    }
});         他には __defineGetter__, __defineSetter__ とか
いよいよプロトタイプ継承の話
●
    ECMA-262 5.1th には以下の画像がある
●   よくわからん
プロトタイプ継承
●   プロパティの探索を、継承先も (さらにその先祖も) 含めて
    行う
    –  クラスベースの言語でのクラスの継承でメソッドの探
       索を継承先クラスまで含めるのと同じ
●   Internal property : [[Prototype]]
    –   継承先のオブジェクト                       obj1
                                    - prop1
                                    - prop2
// 右図の継承構造があるなら
obj1.prop1 = 100;
console.log( obj2.prop1 ); // 100         obj2
                                    - [[Prototype]]
obj1.prop1 = 200;                   - prop3
console.log( obj2.prop1 ); // 200
Object.create メソッド
●   指定したオブジェクトを継承した新しいオブジェクトを生
    成

// 右図の継承構造をつくる
var obj1 = {
    prop1: 100,
    prop2: 200                          obj1
                                   - prop1
};                                 - prop2

// obj2 は obj1 を継承
var obj2 = Object.create(obj1, {         obj2
                                   - [[Prototype]]
     prop3: { value: 300 }         - prop3
});
Object.getPrototypeOf メソッド
●   指定したオブジェクトのプロトタイプ継承先を取得

// 右図の継承構造をつくる
var obj1 = { /* … */ };
var obj2 = Object.create(obj1, {
                                             obj1
    prop3: { value: 300 }               - prop1
});                                     - prop2


// プロトタイプ取得
                                              obj2
Object.getPrototypeOf(obj2) === obj1;   - [[Prototype]]
    // true                             - prop3


                   ブラウザの JavaScript 処理系だと大体
                   __proto__ ってプロパティがある
コンストラクタによるオブジェクト生成
●   “constructor : function object that creates and
    initialises objects” (4.3.4 節)
●   new 演算子

function Cons() {
    this.prop = 200;
}
var obj = new Cons();

console.log( obj.prop ); / 200
                          /
コンストラクタの prototype プロパティ
●   “When a constructor creates an object, that object
    implicitly references the constructor’s “prototype”
    property for the purpose of resolving property
    references.” (4.3.5 節)
    –   コンストラクタの prototype プロパティの値が新たな
        オブジェクトの [[Prototype]] に設定される

                            Cons       Cons.prototype
                         - prototype      - prop1
                                          - prop2



                 obj2
           - [[Prototype]]
           - prop3
おわり

More Related Content

ECMAScript 5 時代のオブジェクト・プロトタイプ継承入門

  • 2. 自己紹介と概要 ● id:nobuoka - はてなブックマークチーム ● Java, JavaScript, Ruby あたりの言語が好き ● 仕事では Perl と JavaScript ● 今日は初心者向けの話 – オブジェクト? – プロトタイプ継承? ● ECMA-262 5.1th ベース
  • 3. ECMAScript とは? ● JavaScript の言語コア部分に相当する言語 ● ECMA International による仕様 : ECMA-262 ● 最新のバージョンは 5.1 – ECMAScript Language Specification (5.1th) – 古い IE では 5.1 の機能が使えなかったりする – プロトタイプ継承などを 5.1 的に説明してみる (本資料中の節番号は ECMA-262 5.1th の節)
  • 4. JavaScript におけるオブジェクト ● 値の一種 : Object 型の値 ● Object 型の他には String 型とか Number 型とか ● JavaScript には C++ や Smalltalk のようなクラスはな い ● オブジェクトリテラルによってやコンストラクタによってな ど、様々な方法で生成される var obj1 = { name : “Hanako”, age : 18 }; var obj2 = new Object();
  • 5. オブジェクトはプロパティの集合体 ● “An Object is a collection of properties.” (8.6 節) ● プロパティ : 名前と値の結合物 (association) – Named data property : プロパティといえばこれ – Named accessor property – Internal property : 仕様説明のための内部的なもの var obj1 = { name : “Hanako”, age : 18 名前は age, 値は数値 }; 18 であるプロパティ
  • 6. オブジェクトの同値性 (概念上の話) ● もっているプロパティの名前が全て同じで、名前に対応す る値も同じ、という 2 つのオブジェクトがあっても、それら のオブジェクトは同じ値ではない ● JavaScript ではオブジェクトそのものが値だから (同じオ ブジェクトでなければ同じ値ではない) // 2 つのオブジェクトは同じ値ではない { p: “y” } !== { p: “y” } 当たり前といえば当たり前。 C から来た人などは戸惑うかも。
  • 7. オブジェクトの同値性 (概念上の話) ● 引数として渡されたオブジェクトに対する操作は、 もとのオブジェクトに影響する (同じ値なので当然) // 引数として渡されたオブジェクトの val プロパティの // 値をインクリメントする関数 function incVal(o) { o.val += 1 } var obj = { val: 10 }; incVal(obj); // incVal 呼び出し後の obj.val の値は 11 『JavaScript 第 5 版』 では 「参照によるデータ操作」 など と説明されている。 実践的にはそれでいいが、仕様を読むに はここで説明したこと (オブジェクトそのものが値) の理解が必要。
  • 8. Accessor property ● いわゆる setter / getter ● 最近のブラウザなら (IE10 含め) 基本的に使える var obj = { _val: 0, get val() { return this._val }, set val(v) { this._val = v } }; obj.val = obj.val + 10;
  • 9. Property Attributes (8.6.1 節) ● プロパティの属性 – [[Value]] : データプロパティの値 – [[Writable]] : 書き換えできるか – [[Set]], [[Get]] : setter / getter – [[Configurable]] : 変更できるかどうか – [[Enumerable]] : for-in ループで列挙されるかどうか ● Object.getOwnPropertyDescriptor (15.2.3.3 節)
  • 10. Object.defineProperty (15.2.3.6 節) ● Property Attributes を指定してプロパティを定義 ● Object.defineProperties もあるよ (15.2.3.7 節) var obj = {}; Object.defineProperty(obj, “newProp”, { value: 200, writable: false }); obj.newProp = 10; // writable : false なので書きこまれない Object.defineProperties(obj, { newProp2: { get: function () { return 200 } } }); 他には __defineGetter__, __defineSetter__ とか
  • 11. いよいよプロトタイプ継承の話 ● ECMA-262 5.1th には以下の画像がある ● よくわからん
  • 12. プロトタイプ継承 ● プロパティの探索を、継承先も (さらにその先祖も) 含めて 行う – クラスベースの言語でのクラスの継承でメソッドの探 索を継承先クラスまで含めるのと同じ ● Internal property : [[Prototype]] – 継承先のオブジェクト obj1 - prop1 - prop2 // 右図の継承構造があるなら obj1.prop1 = 100; console.log( obj2.prop1 ); // 100 obj2 - [[Prototype]] obj1.prop1 = 200; - prop3 console.log( obj2.prop1 ); // 200
  • 13. Object.create メソッド ● 指定したオブジェクトを継承した新しいオブジェクトを生 成 // 右図の継承構造をつくる var obj1 = { prop1: 100, prop2: 200 obj1 - prop1 }; - prop2 // obj2 は obj1 を継承 var obj2 = Object.create(obj1, { obj2 - [[Prototype]] prop3: { value: 300 } - prop3 });
  • 14. Object.getPrototypeOf メソッド ● 指定したオブジェクトのプロトタイプ継承先を取得 // 右図の継承構造をつくる var obj1 = { /* … */ }; var obj2 = Object.create(obj1, { obj1 prop3: { value: 300 } - prop1 }); - prop2 // プロトタイプ取得 obj2 Object.getPrototypeOf(obj2) === obj1; - [[Prototype]] // true - prop3 ブラウザの JavaScript 処理系だと大体 __proto__ ってプロパティがある
  • 15. コンストラクタによるオブジェクト生成 ● “constructor : function object that creates and initialises objects” (4.3.4 節) ● new 演算子 function Cons() { this.prop = 200; } var obj = new Cons(); console.log( obj.prop ); / 200 /
  • 16. コンストラクタの prototype プロパティ ● “When a constructor creates an object, that object implicitly references the constructor’s “prototype” property for the purpose of resolving property references.” (4.3.5 節) – コンストラクタの prototype プロパティの値が新たな オブジェクトの [[Prototype]] に設定される Cons Cons.prototype - prototype - prop1 - prop2 obj2 - [[Prototype]] - prop3