JS 块语句{}

58 阅读3分钟

最近在调试Vue源码的时候,在render模块的mountElement方法, 发现下面这样的代码,

  {
    def(el, "__vnode", vnode, true);
    def(el, "__vueParentComponent", parentComponent, true);
  }

image.png

当时觉得有点新奇,把调用方法写在{}里,和常见的

if (condition) {}
function functionName() {}
class className {}

{}前面拼if, function, class 不一样,顺便说下Vue源码renderer.ts文件,是下面这个样子,没有调用方法,直接写了方法内容。

image.png

在网上查了下,发现是块语句语法,参考块语句文档,块语句用一个{}表示块语句的范围,块语句的语法。

{
  StatementList
}

image.png

块语句在其他语言中通常被称为复合语句。它允许你在JavaScript只期望一个语句的地方使用多个语句。将多个语句组合成块在JavaScript中是一种常见的做法,尤其是与控制流语句如if...else和for结合使用时。相反的行为是使用空语句,在需要语句的地方不提供任何语句。

此外, 结合块作用域声明(如 let、const 和 class),块可以像立即调用的函数表达式(IIFE)一样防止临时变量污染全局命名空间

分割线下面的内容翻译自MDN文档


在非严格模式下使用 var 或函数声明的块作用域规则

使用 var 声明的变量或通过函数声明创建的变量在非严格模式下没有块作用域。在块内引入的变量的作用域是包含它们的函数或脚本,并且设置它们的效果会持续到块之外。例如:

var x = 1;
{
  var x = 2;
}
console.log(x); // 2

这会输出 2,因为块内的 var x 声明与块前的 var x 声明在同一个作用域中。 在非严格模式的代码中,块内的函数声明行为很奇怪。不要使用它们。

在严格模式下使用 let、const、class 或函数声明的块作用域规则

相比之下,使用 let、const 和 class 声明的标识符确实具有块作用域:

let x = 1;
{
  let x = 2;
}
console.log(x); // 1

x = 2 的作用域仅限于其定义的块内。const 也是如此:

const c = 1;
{
  const c = 2;
}
console.log(c); // 1; does not throw SyntaxError

请注意,块作用域内的 const c = 2 不会抛出 SyntaxError: Identifier 'c' has already been declared,因为它可以在块内唯一声明。

在严格模式下,块内的函数声明的作用域仅限于该块,并被提升到块的顶部。

"use strict";

{
  foo(); // Logs "foo"
  function foo() {
    console.log("foo");
  }
}

foo(); // ReferenceError: foo is not defined
举例
使用块语句作为 for 循环的主体

for 循环接受单个语句作为其主体。

for (let i = 0; i < 10; i++) console.log(i);

如果你想在循环体中使用多个语句,可以将它们组合成一个块语句:

for (let i = 0; i < 10; i++) {
  console.log(i);
  console.log(i ** 2);
}
使用块语句来封装数据

let 和 const 声明的作用域是包含它们的块。这使你可以在不将数据包装在函数中的情况下将其隐藏在全局作用域之外。

let sector;
{
  // These variables are scoped to this block and are not
  // accessible after the block
  const angle = Math.PI / 3;
  const radius = 10;
  sector = {
    radius,
    angle,
    area: (angle / 2) * radius ** 2,
    perimeter: 2 * radius + angle * radius,
  };
}
console.log(sector);
// {
//   radius: 10,
//   angle: 1.0471975511965976,
//   area: 52.35987755982988,
//   perimeter: 30.471975511965976
// }
console.log(typeof radius); // "undefined"

模仿一下调试vue源码vue.global.js的写法

function min(a,b) {
  console.log(Math.min(a,b))
}
function max(a,b) {
  console.log(Math.max(a,b))
}
{
  min(2,10)   // 输出2
  max(100,1)  // 输出100
}

image.png