变量作用域
在javascript中,用关键字var声明的变量是有作用域的。
1、如果变量是在函数内部声明的,则该变量的作用域为整个函数体,在函数外部不可引用该变量。
function abs () {
var x = 1; //在函数内部声明变量
x = x * 2;
}
x = x * 4; //报错,函数外部不能引用在函数内部声明的变量
2、如果两个不同的函数声明了相同的变量,则该变量只在各自的函数体内部起作用,即该变量的作用域在各自所在的函数体内部,不同函数体内部声明的相同的变量相互独立。
function abs () {
var x = 10;作用域为该函数体内部
}
function foo () {
var x = "a";//作用域为该函数体内部
}
3、在函数内部定义函数,即函数的嵌套,内部函数可以引用外部的变量,但外部函数不用引用内部函数的变量。
function abs () {
var x = 1;//作用域为整个函数体。
function foo () {
var y = x * 3; //作用域为内部函数的整个函数体。foo可以访问abs中的变量x。
}
var z = y * x; //报错,abs不能访问foo中的变量。
}
4、在嵌套的函数体中,内部函数与外部函数的变量同名,根据javascript函数查找变量是从自身函数定义开始的性质,由“内”向“外”查找,内部函数变量会“屏蔽”外部函数的变量。
function abs () {
var x = 1;
function foo () {
var x = 'A';
alert('x in foo() = ' + x); // 'A'
}
alert('x in abs() = ' + x); // 1
foo();
}
变量提升
javascript函数定义有个特点,它会先扫描整个函数体的语句,把所有声明的变量提升到函数体内部的顶部。注:是提升变量的声明,没有提升变量的赋值,即该变量的值为undefined。
function abs () {
var x = 'Hello, ' + y;
alert(x);
var y = 'Bob';
}
abs();
语句"
var x = 'Hello, ' + y;"不会报错,原因是变量y在后面声明了,但显示的是"Hello,undefined",说明y的值为undefined,这是因为javascript引擎把变量声明提升了,但未提升变量的值。
对于上述代码,引擎所"看到"的是:
function abs () {
var y; //并未初始化,此时y的值为undefined
var x = 'Hello, ' + y;
alert(x);
y = 'Bob'; //此时再给y赋值。
}
abs();
介于javascript函数有这样“怪异”的特性,所以建议在函数内部声明变量,严格遵循 在函数内部首先声明所有变量 这一规则,常见的做法就是使用关键字var声明多个变量。
全局作用域
不在任何函数内部声明的变量具有全局作用域,在javascript中默认有一个全局对象window,全局作用域的变量是被绑在全局对象window上的一个属性。
不用关键字var声明的变量是全局变量,它的作用域为全局作用域,当然,我们不建议这样使用。
var x = "This is javascript!";
alert(x); //This is javascript!
window.alert(x); //This is javascript!
"alert()"与"window.alert()"效果是一样的。
我们知道,函数的定义有两种方式,其中一种就是将函数赋值给一个变量,即"var abs = function () {...}",abs函数也是一个全局变量,它的作用域为全局作用域,也可以用window.表示。
var abs = function () {
alert("This is javascript!")
};
abs();
window.abs(); //相同效果
在javascript中,只有一个全局作用域,如果没在当前函数作用域中找到该变量,则会继续向上(由“内”向“外”)找,最后如果在全局作用域中也没找到,则会报错。
在ES6中,用关键字let来声明变量,使该变量具有块级作用域。
常量
在ES6之前,用var和let不能声明一个常量(如:var PI = 3.14;),在ES6中可以使用关键字const来定义常量,const和let具有块级作用域。
const PI = 3.14,
PI = 3.1415;