20.作用域

2022-02-07  本文已影响0人  静昕妈妈芦培培

ES5中作用域的理解

ES5中:

1.没有块级作用域

因为es5没有块级作用域,在es5环境中下面的花括号形同虚设

{
  var foo = 123
}
console.log(foo) // 123
image.png

2.只有两种作用域:全局作用域和函数作用域

因为函数有作用域,父作用域无法访问子作用域中的变量,子作用域中可以通过作用域链访问父作用域中的变量

var flag = 789
function bar() {
  //函数bar的作用域的父作用域为全局作用域
  var baz = 456
  console.log(flag) // 789
}
bar()
console.log(baz) // Uncaught ReferenceError: baz is not defined
image.png

ES6中块级作用域的理解

1.ES6的代码块级作用域:对let/const/function/class声明的类型有效,对var声明的变量无效
{
  let foo = 123;
}
console.log(foo); // Uncaught ReferenceError: foo is not defined
{
  const bar = 456;
}
console.log(bar); // Uncaught ReferenceError: bar is not defined
{
  class Person {}
}
const p = new Person(); // Uncaught ReferenceError: Person is not defined
{
  var baz = 789;
}
console.log(baz); // 789 ES6的块级作用域对var声明的变量无效
image.png
{
  var baz = 789;
  let foo = 123;
  const bar = 456;
  class Person {}
}
console.log(baz); //789 ES6的块级作用域对var声明的变量无效
console.log(foo); // Uncaught ReferenceError: foo is not defined
console.log(bar); //因为上行代码报错,不会执行
const p = new Person(); //因为上行代码报错,不会执行
image.png
2 function:具有特殊性
{
  function mul(a, b) {
    return a * b;
  }
}
mul(2, 3); // 6
image.png

3.if/switch/for的块代码的块级作用域

3.1.if语句的代码块是有块级作用域的
const flag = true;
if (flag) {
  var foo = 123;
  let bar = 456;
}
console.log(foo); //123
console.log(bar); // Uncaught ReferenceError: bar is not defined
3.2.switch语句的代码块是有块级作用域的
const color = "red";
switch (color) {
  case "red":
    let bg = "red";
    break;
  default:
    break;
}
console.log(bg); // Uncaught ReferenceError: bg is not defined
3.3.for循环的代码块是有块级作用域的
for (let i = 0; i < 10; i++) {
  console.log("btn", i);
}
console.log(i) // Uncaught ReferenceError: i is not defined

for (var j = 0; j < 10; j++) {
  console.log("btn1", j);
}
console.log(j) //10

4.块级作用域的应用场景

const btns = document.getElementsByTagName("button");

//总共有四个按钮,下面代码的实现,会使不管哪个按钮被点击,都输出第4个按钮被点击,
// 因为块级作用域对var声明的变量无效
for (var i = 0; i < btns.length; i++) {
  btns[i].onclick = function () {
    console.log("第" + i + "个按钮被点击");
  };
}

在es6的块级作用域出现之前,使用立即执行函数实现,因为函数有作用域.那时的作用域也只有全局作用域和函数作用域

for (var i = 0; i < btns.length; i++) {
  (function (n) {
    btns[n].onclick = function () {
      console.log("第" + n + "个按钮被点击");
    };
  })(i);
}

有了es6的块级作用域后,这种问题就很容易被解决

for (let i = 0; i < btns.length; i++) {
  btns[i].onclick = function () {
    console.log("第" + i + "个按钮被点击");
  };
}

5.let/const的暂时性死区

var foo = 'abc'

if(true) {
  console.log(foo) //Cannot access 'foo' before initialization
  let foo = '123'
}
675cd364f2c8d6e61253c499bc8534b.png

非常感谢王红元老师的深入JavaScript高级语法让我学习到很多 JavaScript 的知识

上一篇 下一篇

猜你喜欢

热点阅读