😀

newで独自オブジェクトを作る

2020/10/27に公開

はじめに

JavaScriptの話です。

newで独自オブジェクトを作る方法を示します。この際、関数が重要な役割を果たします。

本稿の前提条件

  • JavaScriptの関数を知っている

ハッシュ/連想配列とオブジェクト

ハッシュ/連想配列

次のコードがあったとします。

var e1 = {"name": "佐藤三郎", "age": 60};

ここで{}でくくられたもの (e1に代入されるモノ)を「ハッシュ」とか「連想配列」とかと言うと思います。

次のコードのように、ハッシュの要素は読み書きが自由にできます。

var e1 = {"name": "佐藤三郎", "age": 60};
console.log(e1.name); // "佐藤三郎" と出力
e1.name = "山本五郎";
console.log(e1.name); // "山本五郎" と出力

ハッシュ/連想配列とオブジェクトとは同じ

先ほどのハッシュ/連想配列とオブジェクトは、JavaScriptでは同じものです。
たとえば、var e1 = {"name": "佐藤三郎", "age": 60};は次のように書き換えられます。

var e1 = new Object();
e1.name = "佐藤三郎";
e1.age = 60;
console.log(e1.name); // "佐藤三郎" と出力

newで独自のオブジェクトを作る

さきほどのnew Object()で空っぽのオブジェクトが生成されました。そのほかには new Date()で日付オブジェクトが生成されたりします。これらは、処理系が用意してくれているオブジェクトです。

独自のオブジェクトを作りたい場合には関数を使います。なんか不思議な感じがするかも知れませんが、すぐに慣れます。

とりあえずコードを見てみましょう。

/*
 * Person 人のデータ
 * @param name 氏名
 * @param age 年齢
 */
function Person(name, age) {
  this.name = name;
  this.age = age;
}

var p1 = new Person("山田太郎", 30);
var e1 = {"名前": "佐藤三郎", "age": 60};

console.log(p1.name); // 山田太郎
console.log(e1.name); // 佐藤三郎

これでp1が"name"に対応する値を持つものが本当に出るのかと思われるかも知れませんが、本当に出ます。

newで何をやっているか

new <関数名> (<引数1>,...)は、裏では次のことを順次実行します。

  • 空っぽのオブジェクト (=ハッシュ) を生成する
  • 「生成したオブジェクト」の__proto__に関数のprototypeを代入
  • 呼ばれる関数内に限定してthisキーワードで「生成したオブジェクト」を参照できるようにする
  • 引数はそのままで関数を呼び出す
  • this (=生成したオブジェクト) を返す

new Person(a,b)を関数にしてしまうと次のようになります。

function Person生成(a, b) {
  // 空っぽのオブジェクトを生成
  var ret = {};
  // __proto__にPerson.prototypeを代入
  ret.__proto__ = Person.prototye;
  // thisキーワードで「生成したオブジェクト」を参照できるようにしたうえで
  // Person関数を呼び出す
  // (こういう関数があると思ってください)
  Person.call(ret, a, b);
  // 生成したオブジェクトを返す
  return ret;
}

ただし Person.call(ret, a, b) の実引数と呼ばれた関数Person()の仮引数の対応は次のようになるものとします。

呼び出し元の実引数 呼ばれた関数Person()の仮引数
ret (第1引数) this (仮引数ではない)
a (第2引数) name (第1引数)
b (第3引数) age (第2引数)

関数内でthisを使って初期化

Person()はオブジェクトの初期化を行います。こういう機能を持つ関数はコンストラクタと呼ばれます。

Person()の中でthisを使っていますが、前述の通り、Person生成()内で言うところのretと同じオブジェクトを参照しています。よって、たとえば、Person()内でthis.name="山田"と実行することと''Person生成()ret.name="山田"``と実行することとは同じになります。

おわりに

newで独自オブジェクトを作る方法を示しました。
少しずつステップアップして、継承まで行きたいと思います。

本記事のライセンス

クリエイティブ・コモンズ・ライセンス
この記事は クリエイティブ・コモンズ 表示 4.0 国際 ライセンス の下に提供されています。

Discussion