一、块级作用域与嵌套、let、暂时性死区
admin
2024-05-01 19:29:35
0

ES6+前导以及回忆知识

有些浏览器不兼容ES6+语法:

解决方案:ES6+ ——编译器(例如babel)——> ES5

而babel这种工具需要包管理工具,例如npm来安装。(这里包package代表代码块/功能块)。

而npm只能在node环境中实现;node也是能运行js代码的环境。

共享包:git工具,代码管理工具。


函数执行前预编译过程:AO,即生成函数上下文过程:

  1. 寻找函数形参和变量声明提升
  2. 把实参赋值给形参
  3. 寻找函数声明,赋值函数体
  4. 然后执行函数。(不属于预编译过程,执行完毕AO完整)

函数的参数相当于函数内部声明的变量;

一、块级作用域与嵌套、let、暂时性死区

解决变量污染的原则:KISS原则,keep it simple,stupid。

结论先行:let本质就是为了js增加一个块级作用域。

块级作用域形式上模样:{...}

1.1 let在同一作用域下不可重复声明

同一作用域:块级作用域,函数作用域,全局作用域。

注:块级作用域是他们的子集。

重复声明的例子:

// Uncaught SyntaxError: Identifier 'a' has already been declared
let a = 1;
let a = 2;// Uncaught SyntaxError: Identifier 'a' has already been declared
function test(){let b = 1;var b = 2;
}
test();

函数中的参数相当于在函数内部声明的变量,违反let在同一作用域下不能重复声明的原则。

// Identifier 'a' has already been declared
function test(a){let a = 1;
}
test();

1.2 let不会声明提升,会产生一个暂时性死区

let不会声明提升,在let声明之前会产生暂时性死区,即无法访问这个变量。

TDZ:temporal DeaD Zone 暂时性死区

声明提升是在预编译的过程中,无论是在函数预编译还是全局预编译。

console.log(a); //undefined
var a = 10;// Uncaught ReferenceError: Cannot access 'b' before initialization
console.log(b);
let b = 2;// Uncaught ReferenceError: Cannot access 'b' before initialization
function test(){console.log(b);let b = 2;
}
test();

再举一个ES6暂时性死区问题:

// Uncaught ReferenceError: Cannot access 'y' before initialization
function test(x = y, y = 2){console.log(x,y);
}
test();

暂时性死区导致typeof不再安全:

console.log(typeof(a)); //undefined// Uncaught ReferenceError: Cannot access 'b' before initialization
console.log(typeof(b));
let b;

1.2 let只能在当前作用域下生效

遵守了let在同一作用域下不可重复声明的原则,同时只在当前块级作用域之内生效。

function test(a){{let a = 10;}console.log(a);
}test();//undefined

let只能在当前作用域下生效:

// 例1:Uncaught ReferenceError: b is not defined
{let b = 1;
}
console.log(b);// Uncaught ReferenceError: a is not defined
if(1){let a = 1;
}
console.log(a);// 例2:死循环,永远不会报错
for(;1;){let a = 1;
}
console.log(a);

打印0-9:

var arr = [];
// 打印0-9
for(var i = 0; i < 10; i++){arr[i] = function(){console.log(i);}
}
for(var i = 0; i < 10; i++){arr[i]();
}

打印10个10:

var arr = [];
for(var i = 0; i < 10; i++){arr[i] = function(){console.log(i);}
}
for(var j = 0; j < 10; j++){arr[j]();
}

打印0-9,与上面打印10个10不同的地方在于,for循环中使用let声明变量,原因:

let创建了块级作用域,每次循环时内部的块级作用域都会去访问外层块级作用域中的变量i,而外层块级作用域中的变量i都不同,所以打印0-9

var arr = [];
for(let i = 0; i < 10; i++){arr[i] = function(){console.log(i);}
}
for(var j = 0; j < 10; j++){arr[j]();
}

打印报错原因:

var变量提升在作用域中是逐级往外提升的;也就是说var变量逐级提升的过程中,只要和let声明的变量处在同一个作用域内,就会报错。报错原因是:let在同一作用域下不可重复声明。

// 打印报错:Uncaught SyntaxError: Identifier 'i' has already been declared
for(let i = 0; i < 10; i++){var i = 'a';console.log(i);
}

打印了10个a:let定义的变量不在同一个作用域内,即使名字相同也不是同一个变量

for(let i = 0; i < 10; i++){let i = 'a';console.log(i);
}

相当于:

{let i = 0for(; i < 10;){{let i = 'a';console.log(i);}i++;}}

内层作用域可以更改外层作用域中的let声明的变量:

if(1){let a = 1;{a = 10;console.log(a); // 10}console.log(a); // 10
}

而let定义的变量不在同一个作用域内,即使名字相同也不是同一个变量:

if(1){let a = 1;{let a = 10console.log(a); // 10}console.log(a); // 1
}

补充:

  1. ES5中函数声明的位置:顶层作用域,函数作用域。

    ES6可以在块级作用域中声明函数,浏览器可以兼容,但不推荐这样使用——>在块级作用域中使用函数表达式代替函数声明。

if(i){function test(){}
}try {function test(){}
}catch(e){function test1(){}
}

解决方案:在块级作用域中使用函数表达式代替函数声明。

try {var test = function(){}
}catch(e){var test1 = function(){}
}
  1. 块级作用域没有返回值
  2. 块级作用域等于匿名函数的立即调用 ×,首先两个是不同的概念,其次块级作用域没有返回值。
if(1){let a = 1;{(function(){a = 10;console.log(a); //10})();}console.log(a); //10
}
// ------------------------------------------------------------------
if(1){let a = 1;{(function(){var a = 10;console.log(a); //10})();}console.log(a);//1
}
// ------------------------------------------------------------------
if(1){let a = 1;{(function(){let a = 10;console.log(a); //10})();}console.log(a);//1}

相关内容

热门资讯

2026年热门AC游戏推荐及下... AC游戏有哪些值得尝试的佳作?结合热门动漫IP打造的互动体验,往往能迅速俘获二次元玩家的心。本文聚焦...
2026年值得玩的上海滩题材游... 上海滩题材游戏以20世纪二三十年代的上海为历史蓝本,深度还原老上海的城市肌理、建筑风格与市井文化,融...
2026热门乒乓球手游推荐:好... 专注还原专业乒乓球竞技规则的移动游戏,融合多种对战模式与差异化球拍物理反馈,带来沉浸式乒乓体验。本期...
高人气免流量小游戏哪里下载 2... 在现实生活中,很多小伙伴都会出现流量不够用的情况,此时我们可选择能够单机运行免流量小游戏,纯单机模式...
2026热门饥饿游戏盘点 多人... 现在很多玩家对手游的需求早就不是随便点点就完事了,更想要那种有代入感、能让人沉浸进去的体验。饥饿游戏...
《遗忘之海》手游新手入门指南:... 《遗忘之海》手游新手入门指南:高效起步不卡关初次进入《遗忘之海》,面对航海、战斗、探索多重系统交织的...
2026好玩的fps游戏有哪些... 现在很多年轻人下班就想找个地方发泄压力。fps游戏正好满足这种需求。如果你对传统打怪升级感到厌倦,想...
2026热门动作冒险手游推荐:... 想要开启一段沉浸感十足的冒险旅程?动作冒险类手游正以丰富的世界观、流畅的战斗体验与高自由度的操作,成...
性价比高的外卖软件推荐:五款实... 外卖与本地生活服务类应用已深度融入现代日常,从订餐配送到同城代办、即时跑腿,用户对工具的便捷性、响应...
噬神者3掉线卡顿帧数低怎么办?... 近期不少玩家在PC端体验《噬神者3》联机共斗时频繁遭遇掉帧、动作延迟、房间异常断开甚至被强制返回初始...