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

17

Click here to load reader

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

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

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

id:nobuoka(@nobuoka)

2012-11-29 Kyoto.js #2

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

自己紹介と概要

● id:nobuoka - はてなブックマークチーム

● Java, JavaScript, Ruby あたりの言語が好き

● 仕事では Perl と JavaScript

● 今日は初心者向けの話

– オブジェクト?

– プロトタイプ継承?● ECMA-262 5.1th ベース

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

ECMAScript とは?

● JavaScript の言語コア部分に相当する言語

● ECMA International による仕様 : ECMA-262

● 最新のバージョンは 5.1

– ECMAScript Language Specification (5.1th)

– 古い IE では 5.1 の機能が使えなかったりする

– プロトタイプ継承などを 5.1 的に説明してみる(本資料中の節番号は ECMA-262 5.1th の節)

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

JavaScript におけるオブジェクト

● 値の一種 : Object 型の値

● Object 型の他には String 型とか Number 型とか

● JavaScript には C++ や Smalltalk のようなクラスはない

● オブジェクトリテラルによってやコンストラクタによってなど、様々な方法で生成される

var obj1 = { name : “Hanako”, age : 18};

var obj2 = new Object();

var obj1 = { name : “Hanako”, age : 18};

var obj2 = new Object();

Page 5: ECMAScript 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 であるプロパティ

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

オブジェクトの同値性 (概念上の話)

● もっているプロパティの名前が全て同じで、名前に対応する値も同じ、という 2 つのオブジェクトがあっても、それらのオブジェクトは同じ値ではない

● JavaScript ではオブジェクトそのものが値だから (同じオブジェクトでなければ同じ値ではない)

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

当たり前といえば当たり前。C から来た人などは戸惑うかも。

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

オブジェクトの同値性 (概念上の話)

● 引数として渡されたオブジェクトに対する操作は、もとのオブジェクトに影響する (同じ値なので当然)

// 引数として渡されたオブジェクトの val プロパティの// 値をインクリメントする関数function incVal(o) { o.val += 1 }

var obj = { val: 10 };incVal(obj); // incVal 呼び出し後の obj.val の値は 11

『JavaScript 第 5 版』 では 「参照によるデータ操作」 などと説明されている。 実践的にはそれでいいが、仕様を読むにはここで説明したこと (オブジェクトそのものが値) の理解が必要。

Page 8: ECMAScript 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;

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

Property Attributes (8.6.1 節)

● プロパティの属性

– [[Value]] : データプロパティの値

– [[Writable]] : 書き換えできるか

– [[Set]], [[Get]] : setter / getter

– [[Configurable]] : 変更できるかどうか

– [[Enumerable]] : for-in ループで列挙されるかどうか● Object.getOwnPropertyDescriptor (15.2.3.3 節)

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

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__ とか

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

いよいよプロトタイプ継承の話

● ECMA-262 5.1th には以下の画像がある

● よくわからん

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

プロトタイプ継承

● プロパティの探索を、継承先も (さらにその先祖も) 含めて行う

– クラスベースの言語でのクラスの継承でメソッドの探索を継承先クラスまで含めるのと同じ

● Internal property : [[Prototype]]

– 継承先のオブジェクト obj1- prop1- prop2

obj2- [[Prototype]]- prop3

// 右図の継承構造があるならobj1.prop1 = 100;console.log( obj2.prop1 ); // 100obj1.prop1 = 200;console.log( obj2.prop1 ); // 200

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

Object.create メソッド

● 指定したオブジェクトを継承した新しいオブジェクトを生成

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

// obj2 は obj1 を継承var obj2 = Object.create(obj1, { prop3: { value: 300 }});

obj1- prop1- prop2

obj2- [[Prototype]]- prop3

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

Object.getPrototypeOf メソッド

● 指定したオブジェクトのプロトタイプ継承先を取得

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

// プロトタイプ取得Object.getPrototypeOf(obj2) === obj1; // true

obj1- prop1- prop2

obj2- [[Prototype]]- prop3

ブラウザの JavaScript 処理系だと大体 __proto__ ってプロパティがある

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

コンストラクタによるオブジェクト生成

● “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

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

コンストラクタの 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- prototype

obj2- [[Prototype]]- prop3

Cons.prototype- prop1- prop2

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

おわり