1.声明在前还是赋值在前
直觉上告诉我们js代码执行是从上而下一行一行执行的,但实际上这种思路是不完全正确的
以下代码会输出什么
a=2;
var a; console.log( a );
正常来说,声明在赋值之后,所以a被重新赋值为undefined,但是真正输出是2
再来看下面代码
console.log( a );
var a=2;
可能根据上面代码的思路,大家认为会输出2 但实际是undefined
var a = 10
var a
console.log(a)
以上代码等同于下面代码
var a
var a
a = 10
console.log(a)
因此到底是声明在前还是赋值在前?
2.执行顺序
包括函数和变量在内的所有声明都会在任何代码被执行前首先被处理,当你看
var a = 2的时候,以为是一个声明,但是js会看成两个声明:var a;和a = 2,第一个声明实在编译阶段进行的,第二个声明会留在原地等待执行阶段
(1)第一个代码片段会被处理成下面的顺序
var a;
a=2;
console.log(a);
(2)第二个代码片段会被处理成下面的顺序
var a;
console.log(a);
a=2
因此打个比方,就是变量或函数的声明被移动到了最上面,这个过程叫提升,因此先声明后赋值
3.函数优先
console.log(a) // ƒ a() {}
function a() {}
var a = 1
函数声明和变量声明都会被提升,但是函数会被首先提升,变量后于函数
foo(); //1
var foo;
function foo() {console.log(1);}
foo = function() {console.log(2);}
这段代码会被理解为
function foo() {
console.log(1);
}
var foo;
foo();
foo = function() {
console.log(2);
}
尽管var foo出现在function foo() {}之前,但它是重复声明,因为函数声明会提升到普通变量之前,但是后面的函数声明却可以覆盖前面的
foo(); // 3
function foo() { console.log( 1 );
}
var foo = function() { console.log( 2 );
};
function foo() { console.log( 3 );
}
4.为什么要存在变量提升
其实提升存在的根本原因就是为了解决函数间互相调用的情况如果没有函数提升,而是按照自下而上的顺序,当isEven函数被调用时,isOdd函数还未声明,所以当isEven内部无法调用isOdd函数。
// 验证偶数
function isEven(n) {
if (n === 0) {
return true;
}
return isOdd(n - 1);
}
console.log(isEven(2)); // true
// 验证奇数
function isOdd(n) {
if (n === 0) {
return false;
}
return isEven(n - 1);
}
5.let声明
- let 声明的变量的作用域是块级的;
- let 不能重复声明已存在的变量;
- let 有暂时死区
(不能在初始化之前使用变量)
,不会被提升。
总结
- 函数提升优先于变量提升,函数提升会把整个函数挪到作用域顶部,变量提升只会把声明挪到作用域顶部
- var 存在提升,我们能在声明之前使用。let、const 因为暂时性死区的原因,不能在声明前使用
- var 在全局作用域下声明变量会导致变量挂载在 window 上,其他两者不会
- let 和 const 作用基本一致,但是后者声明的变量不能再次赋值
网友评论