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下为妥。