JavaScript中非字符串字面量求值规则及未引号length访问异常解析
JavaScript 常见问题解答
1. JavaScript中非字符串字面量是如何求值的?
咱们把不同类型的非字符串字面量拆开说,规则其实挺清晰的:
- 原始类型(数字、布尔、null、undefined):字面量本身就是最终值,比如写
42就直接得到数值42,true就是布尔值true,null和undefined更简单,直接返回自身,没啥额外计算。 - 对象/数组字面量:求值时会先把内部的每个表达式算完,再生成对应的对象。比如
[1 + 2, 'foo' + 'bar'],先算1+2得3,'foo'+'bar'得'foobar',最后生成数组[3, 'foobar']。对象也是一样,{ age: 25 + 5 }会先算出30,再生成{ age: 30 }。 - 函数字面量:只会创建函数对象,不会执行函数体。比如
const add = (a,b) => a+b,写完后add就是这个函数的引用,只有调用add(1,2)的时候才会跑里面的逻辑。 - 正则字面量:直接生成对应的RegExp实例,比如
/abc/g就是一个全局匹配abc的正则对象。
2. 为什么s[length]没报错还返回了第二个字符?
这个问题的核心是变量查找规则和浏览器全局对象的小细节,我给你掰碎了说:
你本来想写的是string["length"](用字符串当属性名,访问字符串的length属性),但写成了string[length]——这里的length是个变量名,不是字符串字面量,JavaScript会这么处理:
- 找
length这个变量:先在当前作用域里找有没有声明过length。如果没声明(就像你的情况),非严格模式下它会自动去全局对象(浏览器里就是window)上找这个属性。 window.length是啥?:浏览器的window.length是当前页面里<frame>或<iframe>的数量。如果你的测试环境刚好有1个框架(比如有些在线编辑器的页面结构带iframe),那window.length就是1。- 字符串的索引访问:用数字(或能转成数字的值)访问字符串的方括号时,会当作字符索引。
'name'[1]就是第二个字符'a'——这就是你看到的结果。
你问是不是length被转成布尔值再转数字?其实不是,逻辑是:先拿到length的实际值(比如1),然后方括号把这个值转成属性名,对字符串来说,数字属性名就会被当作字符索引用。
再补充你的测试案例:
const a = [1,2,3],a["length"]直接访问数组的length属性,返回3;- 如果
length还是1,那a[length]就是a[1],返回数组第二个元素2,和字符串的逻辑一模一样。
要是你开启严格模式(开头加'use strict'),未声明的length会直接报错ReferenceError,就不会有这种意外结果啦。
内容的提问来源于stack exchange,提问作者cham
相关产品推荐
相关产品推荐

