可能的原因
在使用控制台后,我发现以下内容,似乎typeof(a).b 可能等同于typeof (a).b,所以看起来以下内容是等价的
(typeof([].constructor.name)).constructor.name
(typeof [].constructor.name).constructor.name
但是对于第二个示例,似乎执行了以下操作
typeof([].constructor.name).constructor.name
typeof ([].constructor.name).constructor.name
第一个示例中的第二个括号充当分组运算符,这可能是导致奇怪结果的原因
关于 "string" 和 "String" 值
您可能已经知道,我们可以通过 name 属性访问命名函数的名称
function A(){}
A.name // A
此外,当您在窗帘后面创建函数时,会创建一个对象,该对象可通过函数的 prototype 属性访问,该对象通过其 constructor 属性引用函数本身
function A(){}
A.prototype // {constructor: A}
A.prototype.constructor === A // true
每当您创建函数的“实例”时,其隐藏的[[Prototype]] 属性(又名__proto__)都会指向构造函数的原型,所以
[].__proto__ === Array.prototype // true
由于空数组没有定义constructor 属性,JS 会查找__proto__ 指向的对象,如上所示,空数组是Array.prototype,它具有constructor 属性因此
[].constructor === Array // true
从这个地方操作数的分辨率变得微不足道
[].constructor.name // "Array"
[].constructor.name.constructor === String // true
[].constructor.name.constructor.name // "String", i.e. the name of the `function String() {}`
所以在你的例子中
(typeof [].constructor.name).constructor.name
// evaluated to
(typeof "Array").constructor.name
// evaluated to
"string".constructor.name
// evaluated to
String.name
// evaluated to
"String"
第二个例子
typeof ([].constructor.name).constructor.name
// evaluated to
typeof "String"
// evaluated to
"string"
故事的寓意:使用typeof operator 而不是typeof()。