JavaScript语法中声明变量时,我们用var关键字声明和不用任何关键字声明,多数时候结果并没有啥影响。
但是,这两种方式还是有天壤之别的。
1.用var关键字声明
var num = 1;
上述代码,它是在当前作用域中声明变量num。
如是在方法function中声明,则为局部变量(local variable);如是在全局作用域中声明,则为全局变量。
2.不用任何关键字声明
num = 1;
上述代码,事实上是对属性赋值操作。
首先,它会在当前作用域链(例如:如是在方法中声明,则当前作用域链代表 方法局部作用域 和 全局作用域......)中解析 num; 如果在任何当前作用域链中存在num变量,则会执行对num变量赋值; 如果不存在num变量,它才会在全局对象(即当前作用域链的最顶层对象,如window对象)中创造num属性并赋值(例如:window.num)。
attention:它并非声明一个全局变量,而是创建new一个全局对象的属性。
important:在js语法中,变量声明自带不可删除属性,比较var num = 1 与 num = 1,前者是变量声明,带不可删除属性,因此无法使用delete语法删除;后者为最顶层对象全局变量的一个属性,因此可以从全局变量中使用delete删除该对象属性。
概念理解:“变量声明”跟“创建对象属性”在这里的区别?
JavaScript中变量声明、创建属性以及每个对象属性都有一定的标志描述说明它们的属性----例如:只读(ReadOnly)、不可枚举(DontEnum)、不可删除(DontDelete)等等。
代码示例如下所示:
<script type="text/javascript">
function test3(){
// num1为全局变量,num2为window的一个属性
var num1 = 1;
num2 = 2;
// delete num1; 无法删除
// delete num2; 删除
function model(){
var num1 = 1; // 本地变量
num2 = 4; // window的属性
// 匿名函数
(function(){
var num = 1; // 本地变量,只在该 匿名函数中 有效
num1 = 2; // 继承作用域(闭包)
num3 = 3; // 在当前作用域链中not found num3,so new window的属性num3
}())
console.log('model方法最后:','num1='+num1,'num2='+num2,'num3='+num3,);
// model方法最后: num1=2 num2=4 num3=3
}
model();
console.log('test3方法最后:','num1='+num1,'num2='+num2,'num3='+num3,);
// test3方法最后: num1=1 num2=4 num3=3
};
test3();
</script>
attention: 在ECMAScript5标准中,有种“严格模式”(Strict Mode)。
在严格模式中,未声明标识符赋值将会抛引用错误ReferenceError,因此可防止意外的全局变量属性的创造。
目前一些浏览器的新版本已经支持。
attention:在ECMAScript5标准中,创建全局变量属性 应当挂在 window下为妥。