变量的声明方式 var
对于 Var x=1; var y = x;此时,x为基本类型,修改y的值不会影响到x。
而对于对象,函数,数组等类型,均是属于引用类型,vara = [1,2,3];var y = a;
则y是a的一个引用。
需要注意的是:
变量的声明和函数的声明会被提升。
a=1;
console.log(a);
var a;
>>1
此时,并不会出错,原因是var a = 1;这句代码被提升了,其效果相当于
var a;
a =1;
console.log(a);
值得注意的是,
console.log(a);
var a=1;
>>undefined
声明(包括变量声明和函数声明)会被提升,但是赋值并不会被提升。上面的代码会被引擎理解为
var a;
console.log(a);
a =1;
Js的作用域与c/c++的作用域有着非常大的差别,一不小心就会出现各种意想不到的结果。
先从一小段代码讲起:
var a =1;
function b(){
console.log(a);
}
(function top(){
var a= 2;
( function t(){
console.log(a);
})();
b();
})();
>>2
>>1
从输出结果看,并不是都是1或者2,这点就是因为作用域不一样导致。在js中,函数有着自身的作用域,在查找变量的时候,会先在函数自身的作用域中查找。上述例子中,t函数是函数top中的一个函数语句(函数t被一对()包装,此时函数被当成一条语句,在top函数中也访问不到函数t,还有一点值得注意的是,函数t只有在(function t (){ //“此处才能访问” }),(function(){})(),后面的一个括号为立即执行改语句)。所以在t自身的作用域中并没有a这个对象,编译器会沿着作用域往外找,是top函数作用域,找到a为2并输出改值。在执行到b()函数的时候,因为b函数是在全局声明的,所以b函数自身没有a对象的时候,编译器便往上一层作用域查找a对象,即在全局作用域中找到a对象。这便是js中的词法作用域,简单理解和函数声明的位置有关,和调用的位置无关。
if(true){
var a="test!"
}
console.log(a);
>>test!
没有接触过js的人对上述代码也会非常的吃惊,竟然不是抛出ReferenceError。在c/c++中,有块作用域,用{}来包裹。而在js中,当你用var来声明的时候,并不是声明在块作用域中,它会被声明在上一级作用域中,(书中说用let可以声明为块作用域变量。但本人学习js环境不支持let,可能是版本的问题)所以上述代码片段实际是在全局作用域中声明了一个a变量。之后再输出a自然不会有错。不注意这一点很容易导致变量覆盖,从而引起意想不到的错误。对于for()等语句也是一样。
注意:
var a =1;
(function (){
console.log(a);
var a=2;
console.log(a);
})();
>>undefined
>>2
上述代码并不是预1和2,当词法作用域和变量提升结合时就可能会引发这种错误。