小さい頃はエラ呼吸

いつのまにやら肺で呼吸をしています。


基本からしっかりJavaScript(2)

JavaScriptをきっちりマスターすべく、一から勉強してみる。

変数の宣言と参照

JavaScriptにおける変数の宣言と参照とは、「変数名をキー、変数値を値とした、ハッシュテーブルへの読み書き」であるといえます。
(途中省略)...
変数を宣言すると、変数名をキー、undefinedを値とするエントリがハッシュテーブル内に作られます。変数に値を代入すると、ハッシュテーブル内の値が書き換わります。変数の参照は、変数名をキーとして値を取り出す事と等価です。
JavaScriptクロージャを完全理解!スコープチェインを知る(前編) - builder by ZDNet Japan

グローバルオブジェクト

変数を定義した際、その変数は暗黙のうちに変数管理用のハッシュテーブルに変数名と値が格納される。このハッシュテーブルのことを「変数オブジェクト」と呼ぶ。グローバル変数の場合は、グローバルオブジェクト(windowオブジェクト)に格納される。

var num = 0;
alert(num);
alert(window.num);
>>0
>>0
アクティベーションオブジェクト

ローカル変数にもグローバル変数と同様の変数オブジェクト(アクティベーションオブジェクト)が存在し、そこで変数名と値の管理が行われている。この変数オブジェクトは、関数の実行時に生成されるため、関数宣言しただけではアクセスすることができない。

関数呼び出し時に作成される目に見えない変数オブジェクトは、特別に「アクティベーションオブジェクト」と呼ばれる事があります(「Callオブジェクト」としている文献もあります)。
JavaScriptクロージャを完全理解!スコープチェインを知る(前編) - builder by ZDNet Japan

function a() {
  var num = 0;
  return num;
}
alert(a.num);
>>undefined
スコープチェーン

変数オブジェクトを外側に向かって次々とたぐり、参照された変数を探していくという仕組みが「スコープチェイン」と呼ばれるものです。
JavaScriptクロージャを完全理解!スコープチェインを知る(後編) - builder by ZDNet Japan

ある変数にアクセスする際に、はじめにローカルスコープを探索し、見つからなければ、その上位のスコープを順々に探索していく仕組みをスコープチェーンと呼ぶ。以下の例では、関数aの変数オブジェクト内に変数numが存在しないため、その上位のグローバルスコープから変数numを探索し、0が出力される。

var num = 0
function a() {
  alert(num);
}
a();
>>0

プロトタイプ

JavaScriptは、プロトタイプベースのプログラミング言語である。

プロトタイプオブジェクト

プロトタイプベースのオブジェクト指向言語では、オブジェクトは別のオブジェクトをプロトタイプとしてできていると考えます。JavaScriptではこれを暗黙の参照という形で実現しています。オブジェクトAをプロトタイプとしているオブジェクトBは、オブジェクトAに対し暗黙の参照を持っているという状態になります。
プロトタイプ(prototype)によるJavaScriptのオブジェクト指向:CodeZine(コードジン)

すべての関数はすでにprototypeというプロパティをもっている。

function a () {}
alert(typeof a.prototype);
>>object

このため、このprototypeオブジェクトにプロパティやメソッドを追加することで、a関数から生成されたオブジェクトは、aのprototypeオブジェクトのプロパティやメソッドを参照することができるようになる。

function a () {}
a.prototype.name = "a";
a.prototype.getName = function() {
  return this.name;
}
var obj1 = new a();
var obj2 = new a();
alert(obj1.name);
alert(obj2.name);
>>a
>>a
alert(obj1.getName());
alert(obj2.getName());
>>a
>>a
プロトタイプの性質

obj1.nameを変更しても別のオブジェクトには影響がない。これはobj1.nameとobj1.prototype.nameが別物であることを示している。

function a () {}
a.prototype.name = "a";

var obj1 = new a();
var obj2 = new a();
obj1.name = "obj1";
alert(obj1.name);
alert(obj2.name);
>>obj1
>>a

obj1.nameプロパティを削除しても、プロトタイプオブジェクトへの暗黙の参照は生きたままである。

function a () {}
a.prototype.name = "a";

var obj1 = new a();
obj1.name = "obj1";
alert(obj1.name);  //obj1.nameプロパティを上書き
>>obj1
delete obj1.name; //obj1.nameプロパティを削除
alert(obj1.name);
>>a
プロトタイプチェーン

以下のように、あるオブジェクトのプロトタイプであるオブジェクトが、また別のオブジェクトをプロトタイプとしているような構造をプロトタイプチェーンと呼ぶ。

function a () {};
function b () {};
function c () {};

var objA = new a();
objA.prop = "hoge";
b.prototype = objA;

var objB = new b();
c.prototype = objB;

var objC = new c();
alert(objC.prop);
オブジェクトが特定のプロパティを持っているかどうかを調べる

JavaScriptでは全てのオブジェクトに(すなわちObject.prototypeに)、hasOwnPropertyというメソッドが定義されています。これは引数で与えた文字列に一致するプロパティを、そのオブジェクト自身が持っているかどうかを判断してくれるメソッドです。
プロトタイプ(prototype)によるJavaScriptのオブジェクト指向:CodeZine(コードジン)

function a () {};
alert(a.hasOwnProperty("prop"));
>>false
a.prop = "hoge";
alert(a.hasOwnProperty("prop"));
>true