SyntaxError: functions cannot be labelled

函数 声明前带有一个 标签 时,会发生 JavaScript 异常 "函数不能被标记"。

消息

SyntaxError: In non-strict mode code, functions can only be declared at top level, inside a block, or as the body of an if statement. (V8-based)
SyntaxError: In strict mode code, functions can only be declared at top level or inside a block. (V8-based)
SyntaxError: Generators can only be declared at the top level or inside a block. (V8-based)
SyntaxError: Async functions can only be declared at the top level or inside a block. (V8-based)

SyntaxError: functions can only be labelled inside blocks (Firefox)
SyntaxError: functions cannot be labelled (Firefox)
SyntaxError: generator functions cannot be labelled (Firefox)
SyntaxError: async function declarations can't appear in single-statement context (Firefox)

SyntaxError: Unexpected keyword 'function'. Function declarations are only allowed inside block statements or at the top level of a program. (Safari)
SyntaxError: Function declarations are only allowed inside blocks or switch statements in strict mode. (Safari)
SyntaxError: Unexpected token '*'. Cannot use generator function declaration in single-statement context. (Safari)
SyntaxError: Unexpected keyword 'function'. Cannot use async function declaration in single-statement context. (Safari)

错误类型

SyntaxError

哪里出错了?

函数声明不应该被标记,因为标签只应该应用于语句,而不是声明。实际上无法跳转到这个标签。然而,由于一些遗留的 JavaScript 语法规则,错误条件比必要情况稍微复杂一些。

  • 严格模式 中,函数声明绝不允许被标记。
  • 在非严格模式下,函数声明允许被标记,但当该函数是 if 语句的唯一语句时(这本身是一个已废弃的特性)除外。
  • 异步函数、生成器函数和异步生成器函数绝不允许被标记。

错误消息可能会说类似“函数声明出现位置无效”的话,因为当解析器看到标签时,它期望后面跟着一个语句,而函数声明不是一个语句。这取决于错误的视角是标签不能后跟函数,还是函数不能前跟标签。

示例

错误的解析对象字面量

虽然你可能确实希望这个标签能做一些类似跳转目标的事情,但通常你并不打算让它成为一个标签。最常见的情况是你实际上希望它成为对象字面量中的一个属性键。

js
const createObj = () => {
  greet: function greet() { // SyntaxError: functions cannot be labelled
    console.log("Hello");
  }
};

在这里,{...} 实际上不是一个对象字面量,而是 箭头函数 的块体,所以 greet: 成为了一个标签。要解决这个问题,你需要将对象字面量用括号括起来。

js
const createObj = () => ({
  greet: function greet() {
    console.log("Hello");
  },
});

你可能还想在对象字面量中使用 方法语法,这样可以避免这个陷阱。

js
const createObj = () => ({
  greet() {
    console.log("Hello");
  },
});

另见