小さい頃はエラ呼吸

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


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

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

2種類のオブジェクト

JavaScriptには以下の2種類のオブジェクトが存在する。

  • プリミティブ
  • オブジェクト

両者の違いは、その中にさらにオブジェクトを詰め込むことができるかどうかにあります。オブジェクトを詰め込むことができないものをプリミティブと呼び、詰め込むことのできるものをオブジェクトと呼びます。

javascriptでは、オブジェクトには、プロパティ値を設定できるが、プリミティブ値には、プロパティ値を設定できない。
オブジェクトとプリミティブ - へたれのへたれの為のへたれ記 はてなブックマーク - オブジェクトとプリミティブ - へたれのへたれの為のへたれ記

プリミティブ

aにpropというプロパティを追加しようとしてみると、undefinedとなります。

var a = 0;
a.prop = "prop";
alert(a);
alert(a.prop);
>>0
>>undefined
オブジェクト

aに追加したプロパティをalertしてみると、propと表示されます。

var a = {}; // 空のオブジェクト
a.prop = "prop";
alert(a);
alert(a.prop);
>>[object object]
>>prop

オブジェクトの操作

オブジェクトにプロパティを追加する
var a = {};
a.prop = "prop";
alert(a);
alert(a.prop);
>>prop
オブジェクトにメソッドを追加する
var a = {};
a.prop = function() {
  alert("hoge");
}
alert(typeof a.prop);
a.prop();
>>function
>>hoge
オブジェクトからプロパティを削除する
var a = {};
a.prop = "prop";
alert(a.prop);
delete a.prop;
alert(a.prop);
>>prop
>>undefined

関数とオブジェクト

関数

関数は実はオブジェクトです。その証拠に、関数にaに対して新たにプロパティやメソッドを追加することができる。

function a() {}; // 空の関数
a.name = "a";
a.getName = function() {
  return this.name;
}
alert(a.name);
alert(a.getName());
>>a
>>a
関数の定義

関数の定義方法には、次の3つが存在します。

  • 関数宣言(function文)
function a() {
  alert("hoge");
}
  • 関数式(function演算子)
var a = function() {
  alert("hoge");
}
  • Functionコンストラクタ
var a = new Function("alert('hoge');");

Functionコンストラクタはfor/whileなどのループ内、または頻繁に呼び出される関数内で使用するべきではない。Functionコンストラクタは、実行時に呼び出されるたびに新たな関数オブジェクトを生成するため、実行速度低下の原因となるからだ。
第2回 JavaScriptの関数をマスターしよう − @IT はてなブックマーク - 第2回 JavaScriptの関数をマスターしよう − @IT

関数定義と関数式の違い

function() {}とx = function() {}は、動作が微妙に異なります。

関数式や Function コンストラクタで定義されたものとは違い、関数宣言で定義された関数は、関数自体が宣言される前に使用する事ができます。
関数 - MDC はてなブックマーク - 関数 - MDC

これはOK

a();
function a() {
  alert("hoge");
}

これはエラー

a();
var a = function() {
  alert("hoge");
}
無名関数

関数式を用いて以下のようにonload関数を定義することができます。これは、右辺に関数名を定義しないことから、無名関数と呼ばれます。

window.onload = function() {
  alert("hoge");
}

無名関数を用いるメリットには、以下のようなものがあります。

  • 命名する必要の無い関数をシンプルに記述できる
  • (複数ファイルのJavaScriptライブラリを読み込んでいるときなどにおいて)、既存の関数/変数名との衝突を回避できる

【コラム】そろそろきっちりJavaScript (2) 無名関数についてもう少し考える | エンタープライズ | マイコミジャーナル はてなブックマーク - 【コラム】そろそろきっちりJavaScript (2) 無名関数についてもう少し考える | エンタープライズ | マイコミジャーナル

スコープ

JavaScriptには、以下の2つのスコープが存在します。

  • グローバルスコープ
  • ローカルスコープ
グローバルスコープ

プログラム中のどこからでも有効な変数の範囲。以下の例では、関数aにおいて変数宣言時にvarを省略した場合は、グローバル変数となる。

var num = 1;
function a() {
  num = 0;
  return num;
}
alert(a());
alert(num);
>>0
>>0
ローカルスコープ

その変数が宣言された関数の中でのみ有効な変数の範囲。

var num = 1;
function a() {
  var num = 0;
  return num;
}
alert(a());
alert(num);
>>0
>>1
ブロックレベルスコープ

以下のコードからも読み取れるように、ブロックレベルスコープは存在しない。ローカル変数は、宣言された場所とは関係なく、すべて関数の先頭で宣言されたのと同じように振る舞う。ただし、JavaScript1.7からはlet文を用いることで、ブロックレベルスコープを実現することができる。

var sum = 0;
for(var i=0; i<10; i++) {
  sum += i;
}
alert(sum);
alert(i);
>>45
>>10