PAYATHON 2026

JS 对象中使用 WebGL2RenderingContext 常量作键为何报错?

数据小陈

版本 1 报错,是因为对象字面量中的普通属性名不能直接使用 WebGL2RenderingContext.BYTE 这样的成员访问表达式。版本 2 使用计算属性名语法 [expression],先求出常量的值,再用这个值创建属性,实现整数到名称的映射。

这个区别由 JavaScript 的对象字面量语法决定,与 WebGL 常量本身无关。

为什么直接写常量表达式会报错?

问题中的失败写法是:

const WebGlDataTypes = {
  WebGL2RenderingContext.BYTE: "BYTE"
};

普通属性定义的键可以是标识符形式的名称、字符串字面量或数值字面量,例如:

const example = {
  BYTE: "name key",
  "another key": "string key",
  5120: "numeric key"
};

WebGL2RenderingContext.BYTE 是读取属性值的表达式,不能直接放在普通属性名的位置。解析器读到点号时,无法按属性定义的语法继续解析,于是报出 Unexpected token '.'。

此时错误发生在语法解析阶段,代码还没有执行读取 WebGL 常量的操作。

为什么加上方括号就能工作?

对象字面量中的 [expression]: value 表示计算属性名。JavaScript 会计算方括号内的表达式,将结果转换为属性键,再赋予对应的值。

const WebGlDataTypes = {
  [WebGL2RenderingContext.BYTE]: "BYTE"
};

如果该常量可用,且值为 0x1400,键的计算过程如下:

  1. 读取 WebGL2RenderingContext.BYTE,得到 0x1400,也就是十进制的 5120。
  2. 将数值转换为对象属性键字符串 "5120"。
  3. 创建值为 "BYTE" 的属性。

因此,对这项属性来说,下面几种写法的效果相同:

const a = { [WebGL2RenderingContext.BYTE]: "BYTE" };
const b = { 0x1400: "BYTE" };
const c = { "5120": "BYTE" };

读取时,WebGlDataTypes[WebGL2RenderingContext.BYTE] 也会先计算方括号中的表达式,再将数值转换为属性键,因此能找到同一个属性。

完整的修正代码

保留问题中版本 2 的计算属性名即可:

const WebGlDataTypes = {
  [WebGL2RenderingContext.BYTE]: "BYTE",                   // 0x1400
  [WebGL2RenderingContext.UNSIGNED_BYTE]: "UNSIGNED_BYTE", // 0x1401
  [WebGL2RenderingContext.SHORT]: "SHORT",                 // 0x1402
  [WebGL2RenderingContext.UNSIGNED_SHORT]: "UNSIGNED_SHORT", // 0x1403
  [WebGL2RenderingContext.INT]: "INT",                     // 0x1404
  [WebGL2RenderingContext.UNSIGNED_INT]: "UNSIGNED_INT",     // 0x1405
  [WebGL2RenderingContext.FLOAT]: "FLOAT"                  // 0x1406
};

console.log(
  WebGL2RenderingContext.BYTE.toString(16) +
  " = " +
  WebGlDataTypes[WebGL2RenderingContext.BYTE]
);

在这些常量可用的环境中,这条日志的消息内容应为:

1400 = BYTE

原问题预期输出中的 glmodel.js:51 等信息是开发者工具显示的源文件位置,并非这段 console.log 拼接出的字符串。具体文件名和行号取决于代码所在位置。

普通对象查找表为什么可以工作?

问题没有给出另一个普通查找表的具体代码。如果它使用数值字面量或普通名称,例如 { 5120: "BYTE" }、{ BYTE: "BYTE" },这些都是合法的属性定义。

普通属性名不会读取同名变量的值:

const key = 5120;

const byName = { key: "BYTE" };
const byValue = { [key]: "BYTE" };

console.log(byName.key);       // "BYTE"
console.log(byName[5120]);     // undefined
console.log(byValue[5120]);    // "BYTE"

{ key: "BYTE" } 创建的是名为 "key" 的属性;{ [key]: "BYTE" } 会读取变量 key,创建名为 "5120" 的属性。

把原来的表达式改成字符串也能消除语法错误,但会改变查找表的含义:

const table = {
  "WebGL2RenderingContext.BYTE": "BYTE"
};

这时键是完整的字符串 "WebGL2RenderingContext.BYTE",不能通过数值 5120 查到它。

使用时注意什么?

对象的属性键是字符串或 Symbol。这里的整数会转成字符串,但仍可使用原有的数值查询写法。如果业务要求严格区分数字键和字符串键,可以使用 Map。

计算属性名会在创建对象时立即求值,因此运行环境必须提供 WebGL2RenderingContext 及相应常量。若 API 不可用,需要另行处理环境支持问题;这与版本 1 的语法错误是两个独立问题。

备注:内容仅供参考。