变量提升,即程序在自上而下执行之前,在本作用域内,由
var
、function
声明的变量或函数,会被提升到最顶端,之后才开始按代码自上而下的顺序执行。变量的默认初始值为undefined
,而函数则是函数声明的字符串。如下所示:
console.log(a);
console.log(fn);
var a = 10;
function fn() {
console.log(fn);
}
结果如下:
undefined
ƒ fn() {
console.log(fn);
}
示例一:
console.log(a);
console.log(b);
var a = b = 10;
结果如下:
undefined
Uncaught ReferenceError: b is not defined
这里的
b
并不是用var
声明的,所以没有被提升。
示例二:
console.log(a);
console.log(b);
var a , b = 10;
结果如下:
undefined
undefined
这里的
b
相当于使用var
声明
示例三:
console.log(a);
console.log(b);
let a , b = 10;
结果如下:
Uncaught ReferenceError: a is not defined
let
const
class
都不会有变量提升
示例四:
console.log(a);
console.log(b);
let a = b = 10;
结果如下:
Uncaught ReferenceError: a is not defined
由于
let
没有变量提升,所以报错--未被定义
示例五:
console.log(a);
console.log(b);
var a = 10;
b = 10;
结果如下:
undefined
Uncaught ReferenceError: b is not defined
这里的
b
没有使用var
声明,所以没有变量提升
示例六:
console.log(a);
console.log(window.b);
var a = 10;
b = 10;
结果如下:
undefined
undefined
这里
b
并没有使用var
声明,但是由于调用的是window.b
,相当于调用一个对象的属性,属性不存在,返回undefined
,因此不会报错。
示例七:
console.log(a, b); // 变量提升,默认值为 undefined
var a = 10, b = 10;
function fn() {
console.log(a, b); // 由于下一行的 a 使用 var 声明,变量提升,默认值 undefined
// b 不是 var 声明的,不存在变量提升,
// 所以根据作用域链,向上查找,即为全局声明的 b
var a = b = 11;
console.log(a, b);
}
fn();
console.log(a, b); // 在函数中改变了全局变量 b 的值
结果如下:
undefined undefined
undefined 10
11 11
10 11
示例八:
function fn(a) {
n = a;
console.log(a);
console.log(n);
console.log('a' in window);
console.log('n' in window);
}
fn(11);
// console.log(a); // 报错 Uncaught ReferenceError: a is not defined
console.log(n);
结果如下:
11
11
false
true
11
在函数体内,不使用
var
声明的变量(参数是局部变量),会被视为全局变量,假如全局作用域中不存在此变量,则在函数执行时被创建。
示例九:
console.log(fn); // typeof fn ===> undefined
fn();
var fn = () => console.log(11); // typeof fn ===> function
结果如下:
undefined
Uncaught TypeError: fn is not a function
示例中是给使用
var
声明的变量赋值一个匿名函数,所以,fn
作为变量,默认值是undefined
,在赋值之前执行fn()
,相当于执行一个变量,所以产生类型错误。通过之前,和之后的
typeof
可以看出,赋值之前,把fn
作为一个变量,之后把fn
作为一个函数。
示例十:
console.log(a);
if (false) {
var a = 10;
}
console.log(a);
结果如下:
undefined
undefined
由于
var
没有块级作用域,所以声明的a
是全局变量,变量提升默认值是undefined
,由于if
条件为false
,所以不执行赋值操作,最后的值还是undefined
。假如if
条件为true
,则会执行赋值操作。
示例十一:
console.log(f);
// typeof f ===> undefined
if (f()) {
function f() {
return true;
}
}
结果如下:
undefined
Uncaught TypeError: f is not a function
一般情况下,
function
声明的函数,可以在声明之前调用执行如:f(); function f(){return true};
然而,在
if
语句块中(低版本浏览器除外),使用function
声明的函数和var
声明变量一样,都只是先声明,然后变量提升,只有执行到的时候才会赋值,在if
条件中的f
现在还是undefined
,因此,调用f()
会出现语法错误。
示例十二:
console.log(f);
if (true) {
console.log(f);
function f() {
return true;
}
}
结果如下:
undefined
ƒ f() {
return true;
}
注意:
if
条件体内的第一句中f
并不是一个变量,假如是var
声明的变量,值是undefined
,但它是function
声明的函数,所以值是函数声明的字符串。
示例十三:
console.log(a);
var a = 1
function a() {
console.log(1);
}
console.log(a);
// a(); // 这里 a=1 调用变量报错
function a() {
console.log(2);
}
// a(); // 这里 a=2 调用变量报错
var a = 2;
function a() {
console.log(3);
}
var a = () => { }; // 这里的 a 同样只是变量赋值
var a;
function a() {
console.log(4);
}
console.log(a);
结果如下:
ƒ a() {
console.log(4);
}
1
() => { }
在程序执行之前,先要考虑变量提升(除了在函数体内,先形参赋值,再变量提升),开始时使用
var
声明的变量提升,默认值是undefined
,之后再使用var
声明同名的变量,并不会有变量提升,只是相当于赋值操作;而function
声明同名的函数,每次都会变量提升并覆盖初始值,即最后一次的function
声明为默认值。之后,程序开始自上而下执行,越过函数体部分,只有函数再调用时才会进入函数体。假如没有对
a
重新赋值,不管在哪里调用都是对最后一次声明的函数的调用。在调用之前,如果对a
重新赋值(不包括赋值一个匿名函数),a
成为了一个变量,调用变量即会报错。
网友评论