Javascript で変数を宣言する際、var キーワードを使って宣言しても、使わずに宣言しても、多くの場合は実行に問題はありませんが、この2つの方法には違いがあります。正常に実行できるコードが、適切なコードであるとは限りません。
var num = 1;
現在のスコープ内で変数を宣言します。メソッド内で宣言した場合はローカル変数(local variable)となり、グローバルスコープで宣言した場合はグローバル変数となります。
而
num = 1;
実際にはプロパティへの代入操作です。まず、現在のスコープチェーン(メソッド内で宣言した場合、現在のスコープチェーンはグローバルスコープとメソッドのローカルスコープなどを表します。。。)内で num を解決しようとします。現在のスコープチェーンのどこかで num が見つかれば、num プロパティへの代入を実行します。num が見つからなければ、グローバルオブジェクト(つまり現在のスコープチェーンの最上位オブジェクト、例えば window オブジェクト)に num プロパティを作成して代入します。
注意!これはグローバル変数を宣言したのではなく、グローバルオブジェクトのプロパティを作成したのです。
それでも、ここでの「変数宣言」と「オブジェクトプロパティの作成」の違いを理解するのは難しいかもしれません。実際、Javascript の変数宣言、プロパティ作成、そして Javascript の各プロパティには、それらの属性を示す一定のフラグがあります。例えば、読み取り専用(ReadOnly)、列挙不可(DontEnum)、削除不可(DontDelete)などです。
変数宣言には削除不可属性が付いているため、var num = 1 と num = 1 を比較すると、前者は変数宣言であり、削除不可属性を持つため削除できません。後者はグローバルオブジェクトのプロパティであるため、グローバルオブジェクトから削除できます。
// num1为全局变量,num2为window的一个属性
var num1 = 1;
num2 = 2;
// delete num1; 无法删除
// delete num2; 删除
function model(){
var num1 = 1; // 本地变量
num2 = 2; // window的属性
// 匿名函数
(function(){
var num = 1; // 本地变量
num1 = 2; // 继承作用域(闭包)
num3 = 3; // window的属性
}())
}
PS:ECMAScript5 標準には「厳格モード」(Strict Mode)があります。厳格モードでは、未宣言の識別子に代入すると参照エラーが発生するため、意図しないグローバルオブジェクトのプロパティ作成を防ぐことができます。現在、一部のブラウザの新しいバージョンではすでにサポートされています。