JavaScript中使用WebGL2RenderingContext API常量进行对象查找失败的原因解析及可行方案说明
这其实是JavaScript对象字面量语法的基础问题,咱们一步步说清楚:
为什么版本1会报错?
在JavaScript的对象字面量里,常规属性名的写法只能是合法标识符或者字符串字面量。比如:
// 合法:标识符作为属性名 const obj1 = { name: "Alice" }; // 合法:字符串字面量作为属性名 const obj2 = { "user-name": "Bob" };
而你版本1里写的WebGL2RenderingContext.BYTE是一个表达式(它是在访问WebGL2RenderingContext对象的BYTE属性),既不是合法标识符(标识符里不能有.),也不是字符串字面量。JavaScript解析器看到.的时候,会以为这是语法错误——因为它期望属性名写完了,结果突然冒出来一个.,完全不符合预期,所以就抛出了Unexpected token '.'的错误。
简单说就是:你不能直接把表达式放在对象字面量的属性名位置,ES6之前根本不支持这种写法。
为什么版本2能正常运行?
版本2用了ES6(ECMAScript 2015)引入的计算属性名语法,就是用方括号[]把表达式包起来,作为对象的属性名。
当JavaScript解析到[WebGL2RenderingContext.BYTE]时,会先执行这个表达式,拿到它的值(也就是0x1400,十进制的5120),然后把这个值转换成字符串(因为对象的属性键本质上都是字符串或Symbol,数值会自动转成字符串),作为对象的属性键。
换句话说,版本2的代码等价于:
const WebGlDataTypes = { "5120": "BYTE", "5121": "UNSIGNED_BYTE", "5122": "SHORT", // ... 其他对应数值转成字符串的键值对 };
当你后续用WebGlDataTypes[WebGL2RenderingContext.BYTE]查找时,WebGL2RenderingContext.BYTE的数值会被隐式转成对应的字符串,刚好匹配到对象里的键,所以能正确返回对应的名称,这就是它能正常工作的原因。
补充验证
你可以自己测试一下:
console.log(typeof WebGL2RenderingContext.BYTE); // number console.log(String(WebGL2RenderingContext.BYTE)); // "5120" console.log(WebGlDataTypes["5120"]); // "BYTE",和用数值查找的结果一致
内容的提问来源于stack exchange,提问作者Petr Pivonka

