if (true) {
// console.log(aa); // VM439541:1 Uncaught SyntaxError: Identifier 'aa' has already been declaredlet aa = 'aaa';
}
console.log(aa); // VM439096:4 Uncaught ReferenceError: aa is not defined复制代码
在if条件语句内部通过let aa = 'aaa'中的let关键字创建了一个块级作用域,所以我们在外面不能访问aa变量。
console.log(aa); // VM440010:1 Uncaught ReferenceError: aa is not definedlet aa = 'aaa';
复制代码
var aa = 'aaaa';
if (true) { // **** 执行序号 5console.log(aa); // **** 执行序号 6
aa = 1; // **** 执行序号 7functionaa () {} // **** 执行序号 8console.log(aa);
}
console.log(aa);
/**代码分析 执行顺序**/var aa;
aa = 'aaaa';
if (true) {
functionaa () {}
console.log(aa); // function aa () {}
aa = 1;
// function aa () {} 再执行一遍console.log(aa); // 1
}
console.log(aa); // 1 ?这个确定对?复制代码
我们主要观察if内部的aa = 1; function aa () {}的顺序,在当前代码中第二个console.log(aa)会输出一个1,如果我们把aa = 1; function aa () {}改为function aa () {}; aa = 1;它外部的console.log(aa)就会变化,看代码:
var aa = 'aaaa';
if (true) { // **** 执行序号 1console.log(aa); // function aa () {} **** 执行序号 2functionaa () {} // **** 执行序号 3
aa = 1; // **** 执行序号 4console.log(aa); // 1
}
console.log(aa); // function aa () {}/**代码分析 执行顺序**/var aa;
aa = 'aaaa';
if (true) {
functionaa () {}
console.log(aa); // function aa () {}// function aa () {} 再执行一遍
aa = 1;
console.log(aa); // 1
}
console.log(aa); // function aa () {} ?这个确定对?复制代码
第三个console.log(aa)会输出test函数作用域中的aa = 1,因为在执行function aa () {}是都会更新外部变量aa的值为1,也就是test函数作用域中的aa = 1;
第四个console.log(aa)会输出全局作用域中的aa,因为从来没有声明过全局变量aa所以会报错,is not defined。
来两道题
来两道题加深一下印象。
道题
var a = function() {
console.log(1);
};
var a = function() {
console.log(2);
};
var a;
console.log(a);
a = 1;
console.log(a);
a = 2;
console.log(a);
console.log(typeof a);
复制代码
如果只能答出来就没有必要看了。
如果变量提升遇到函数提升,那个优先级更高呢,看下面的代码。
console.log(a); // function a () {console.log(1);}var a = 1;
functiona() {
console.log(1);
}
console.log(a); // 1复制代码
var a = function() {
console.log(1);
};
var a;
console.log(a); // function a () {console.log(1);}
a = 1;
console.log(a); // 1复制代码
我们再来一个稍微复杂一点的,代码如下:
console.log(a); // function a () {console.log(2);}var a = 1;
functiona() {
console.log(1);
}
console.log(a); // 1var a = 2;
functiona() {
console.log(2);
}
console.log(a); // 2console.log(typeof a); // number复制代码
在多次函数提升的会后一个覆盖前一个,然后才是变量提升,其实代码如下:
var a = function() {
console.log(1);
};
var a = function() {
console.log(2);
};
var a;
console.log(a); // function a () {console.log(2);}
a = 1;
console.log(a); // 1
a = 2;
console.log(a); // 2console.log(typeof a); // number复制代码
第二道题
第二道题会比道题难一点点,代码如下:
console.log(aa);
var aa = 'aaa';
if (true) {
console.log(aa);
aa = 1;
functionaa () {}
aa = 2;
console.log(aa);
}
console.log(aa);
复制代码
如果上面的内容看懂了,大概这个题就会感觉很简单,大致过程如下:
个console.log(aa)会输出全局作用域中的aa值为undefined,因为var aa = 'aaa'会产生变量提升,会把var aa;放到全局作用域中的顶端,所以会输出undefined。
第二个console.log(aa)会输出if内部中的aa = ƒ aa () {},if内部执行产生block作用域,并且block作用域内部的ƒ aa () {}被提升到顶部,所以会输出ƒ aa () {}。
第三个console.log(aa)会输出block作用域中的aa = 2,因为在执行function aa () {}是都会更新外部变量aa的值为1,也就是全局作用域中的aa = 1;