语法错误:函数不能被标记

function 声明前面有 label 时,会发生 JavaScript 异常 "函数不能被标记"。

¥The JavaScript exception "functions cannot be labelled" occurs when a function declaration has a label before it.

信息

¥Message

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)

错误类型

¥Error type

SyntaxError

什么地方出了错?

¥What went wrong?

函数声明永远不应该被标记,因为标签应该只适用于语句,而不是声明。没有办法真正跳转到此标签。但是,由于一些遗留的 JavaScript 语法规则,错误条件比必要的要复杂一些:

¥Function declarations are never supposed to be labeled, because labels should only apply to statements, not declarations. There's no way to actually jump to this label. However, due to some legacy JavaScript syntax rules, the error condition is a bit more complicated than necessary:

  • 严格模式 中,函数声明永远不允许被标记。
  • 在非严格模式下,允许对函数声明进行标记,但当函数是 if 语句的唯一语句时则不允许(这本身是一个已弃用的功能)。
  • 异步函数、生成器函数和异步生成器函数永远不允许被标记。

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

¥The error message may say something along the lines of "invalid place for a function declaration to appear", because when the parser sees a label, it expects a statement to follow, and a function declaration is not a statement. It depends on whether the error's perspective is that a label cannot be followed by a function, or that a function cannot be preceded by a label.

示例

¥Examples

错误解析的对象文字

¥Misparsed object literal

虽然你实际上可能希望标签执行类似跳转目标的操作,但通常你并不打算将其作为标签。最常见的情况是你实际上希望它成为对象文字中的属性键:

¥While it's possible that you actually expect the label to do something along the lines of being a jump target, usually you didn't intend for it to be a label. The most common case is you actually want it to be a property key in an object literal:

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

这里,{...} 实际上不是对象文字,而是 箭头函数 的块主体,因此 greet: 成为标签。要解决此问题,你需要将对象文字括在括号中:

¥Here, {...} is actually not an object literal, but is instead the block body of the arrow function, so greet: becomes a label. To fix this, you need to wrap the object literal in parentheses:

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

你可能还希望将 方法语法 用于对象文字,这样可以避免这个陷阱:

¥You may also want to use the method syntax for object literals, which avoids this pitfall:

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

也可以看看