You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

BindingIdentifier与IdentifierReference的区别是什么?

Why are BindingIdentifier and IdentifierReference distinguished in ECMAScript?

Great question! At first glance, these two productions look identical, but they serve completely different roles in the ECMAScript grammar—this is a classic case of syntactic context defining meaning, even when the tokens are the same.

First, let's recap the relevant grammar productions from the spec:

IdentifierReference[Yield, Await]:
    Identifier
    [~Yield]yield
    [~Await]await

BindingIdentifier[Yield, Await]:
    Identifier
    [~Yield]yield
    [~Await]await

Identifier:
    IdentifierName but not ReservedWord

Core Differences Between the Two


1. Purpose: Reference vs. Binding

  • IdentifierReference is for looking up an existing name (reading its value). It's used whenever you want to access a variable, function, or property that's already been declared.
    • Example: const total = price + tax — here price and tax are IdentifierReferences, since we're referencing values that should already exist in scope.
  • BindingIdentifier is for creating a new name binding (declaring a variable/identifier). It's how you introduce a new name into the current scope.
    • Example: let tax = 0.08 — here tax is a BindingIdentifier, since we're defining a new variable.

2. Grammatical Context

The spec uses these productions in entirely separate contexts:

  • IdentifierReference appears in expression contexts: think function calls (myFunc()), member access (obj.prop), or any place where you're evaluating a value.
  • BindingIdentifier appears in declaration contexts: variable declarations (var/let/const), function parameters, function names, catch clause bindings, destructuring patterns (const { name } = user), etc.

3. Reserved Word Handling

While both allow yield and await under specific conditions, the rules differ based on their role:

  • For IdentifierReference: yield is allowed as an identifier only in non-generator functions, and await only in non-async functions. In generator/async code, they act as keywords and can't be referenced as identifiers.
  • For BindingIdentifier: You can declare let yield; or const await; only in contexts where the Yield/Await grammar parameter is set to ~ (i.e., non-generator/non-async code). Inside a generator function, declaring let yield; is invalid, since the context enforces yield as a keyword.

Why This Distinction Matters


This separation eliminates ambiguity in the grammar. Without it, the parser couldn't tell if a token like x is meant to create a new binding (e.g., in let x = 5) or reference an existing one (e.g., console.log(x)). It also lets the spec enforce strict scoping rules, ensuring that names are declared before they're referenced, and that reserved words are handled correctly depending on the context.

内容的提问来源于stack exchange,提问作者MaximPro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:05:40