Tips

JavaScriptのprototypeとは何者なのか?

  • このエントリーをはてなブックマークに追加

「prototype」というワードだけ聞くと初見のものに感じられるかもしれません。

しかし意外と多くの人が「prototype」をコンソールで見たことがあります。

JavaScriptのprototypeはオブジェクトを継承して自作の関数を入れ込むために使用します。

今回は基本的な使い方とよくある注意点を紹介します。

また動画もあるので必要に応じて活用してください。

JavaScriptにおけるprototypeとは?

以下のような配列を例題にします。

const array = [1, 2, 3, 4];
console.log(array);

console.log( )を使うことで引数のデータについて表示することができるのですが、配列の場合だと上図のように「Prototype」というものが見えます。

これが本題のprototypeのことです、中を開けると何やら大量の文字が格納されています。

よくよく見てみると「pop」「map」「join」などJavaScriptでお馴染みの関数の名前が書いてありますね。

prototypeとは「対象のデータに使用できる関数の一覧」になっています。

あらかじめJavaScript側で用意してくれているものですね。

ちなみにprototypeはデータ型によって表示内容が若干違います。

const data = {
  id: "0001",
  name: "AAA",
  age: 20,
};
console.log(data);

「Prototype」の名前が先ほどは「Array」でしたが今回は「Object」になっています。

また「Prototype」を開いた結果も違う内容になっているのが分かります。

JavaScriptでprototypeに自作の関数を設定する方法

今回は自分で作った関数をprototypeの中に設定するということをやってみたいと思います。

関数そのものは文法は同じなのですがprototypeの中に設定するには以下のように書きます。

// ここを追加
Array.prototype.sayHello = function () {
  console.log("hello");
};

const array = [1, 2, 3, 4];
console.log(array);

関数の中身はコンソールに「hello」と表示するだけの簡単なもので、「Prototype名 . protoype . 関数名」という書き方になります。

今回は定数arrayで実験してみますすのでPrototype名は「Array」になります。

コンソールの表示は冒頭でやったものと変化ないですがPrototypeの中を開けてみると自分で作ったsayHelloが設定できているのが分かります。

自作した関数が設定できた後は、その関数を使いたい場所で使うだけです。

関数を使用する時は通常の文法と同じで大丈夫です。

Array.prototype.sayHello = function () {
  console.log("hello");
};

const array = [1, 2, 3, 4];
console.log(array);

// sayHelloを使用
array.sayHello(); 「hello」と出力される

JavaScriptのprototypeを使う上で注意したいこと

自作の関数を簡単に組み込み関数として設定することができました。

しかし簡単がゆえに注意しないといけないことがあります。

例えばすでにJavaScriptが用意している既存の関数と同じ名前で関数を設定してみます。

// pushという名前で自作の関数を設定
Array.prototype.push = function (val) {
  console.log(val);
};

// pushを使う
array.push(5);
console.log(array);

JavaScriptにはpushという関数があり、引数に入れたものを配列に追加するための関数です。

このpushと全く同じ名前で自作の関数をprototypeに設定してみました。

自作の関数の中身が引数を受け取って、その引数の内容をコンソールログに表示するものです。

array.push(5)とすると自作した方の処理が実行されており、元々のpushの効果である配列の中身を増やすことはできていません。

prototypeでは名前が被ると処理内容が上書きされることになっています。

そのためpushのようにJavaScriptで用意している関数と同じ名前は避けて使う必要があります。

とはいえ仮にオリジナルの名前を作ったとしても、長い目で見た時にJavaScript側や他の開発者によって「逆に上書きされる」なんてことも考えられます。

オリジナルの名前を考えるのはもちろんですが、JavaScriptではSymbolという関数を使うことで上書き防止をしてくれます。

// 「push」という名前を上書きしないようにする
const push = Symbol();
Array.prototype[push] = function (val) {
  console.log(val);
};

array[push](5);
array.push(5);
console.log(array);

prototypeに登録したい関数名を定数としてSymbol( )を格納しておくことで上書き防止ができます。

またSymbolした名前をprototypeで登録する際にはArray.prototype[push]のようにドットで繋げずに[ ]で書きます。

さらにSymbolした名前で登録した関数を使うときもarray[push](5)のように、こちらもドットで繋げずに[ ]で書くのがルールです。

コンソールの表示結果としては自作のpushとJavaScript側でもともと用意していたpushの両方を実行することができています。

// 「push」という名前を上書きしないようにする
const push = Symbol();
Array.prototype[push] = function (val) {
  console.log(val);
};

// 自作した方のpush
array[push](5);
// もともとあった既存のpush
array.push(5);
console.log(array);

このようにprototypeに自作の関数を設定する際にはSymbolで名前を守ることを覚えておきましょう。

また今回参考にした本はこちらになります。

良ければどうぞ。

  • このエントリーをはてなブックマークに追加