当我将name
属性添加到Object.prototype
并引用Object.prototype
时,我收到以下错误:
TypeError: Cannot read property '0' of undefined"
但我可以阅读Object.prototype.name
。 name
属性对Object.prototype
有什么特别之处吗?为什么会出现这种错误?
代码已在Mac OS X上的Node v6.9.5环境中执行。有谁知道如何解决这个问题?
$ node
> Object.prototype
{}
> Object.prototype.value = 'foo';
'foo'
> Object.prototype.name = 'bar';
'bar'
> Object.prototype
TypeError: Cannot read property '0' of undefined
> Object.prototype.name
'bar'
> Object.prototype.value
'foo'
> delete Object.prototype.name
true
> Object.prototype
{ value: 'foo' }
> Object.prototype.name = 'bar';
'bar'
> Object.prototype
TypeError: Cannot read property '0' of undefined
> delete Object.prototype.value;
true
> Object.prototype
TypeError: Cannot read property '0' of undefined
at Object.stylizeWithColor [as stylize] (util.js:242:43)
at formatProperty (util.js:814:18)
at util.js:654:12
at Array.map (native)
at formatObject (util.js:653:15)
at formatValue (util.js:592:16)
at Object.inspect (util.js:186:10)
at REPLServer.self.writer (repl.js:468:19)
at finish (repl.js:593:38)
at REPLServer.defaultEval (repl.js:385:5)
答案 0 :(得分:5)
经过一番检查后,我找到了罪魁祸首,是的,问题是"name"
以特殊方式使用。
此错误与JavaScript无关,它是Node REPL代码中的一个错误,它会对输出进行样式设置。
由于我们正在打印对象,因此代码最终会执行this function:
function formatObject(ctx, value, recurseTimes, visibleKeys, keys) {
return keys.map(function(key) {
return formatProperty(ctx, value, recurseTimes, visibleKeys, key, false);
});
}
value
是Object.prototype
,{ name: 'bar' }
和keys
是单个元素的数组,即["name"]
。
对于此单个键"name"
,执行继续到formatProperty
,它会跳过检查以使用getter / setter或符号格式化对象,并在{{3}上调用formatValue
}}。此调用返回我们应该打印的值的颜色编码表示,在我们的示例中类似"[32m'bar'[39m"
。
接下来,代码尝试构建一个字符串以显示正在打印的上下文。这是与正在打印的数据类型相对应的字符串,例如[Object]
,[Getter]
等。执行this line:
ctx.stylize(name, 'name');
第一个参数name
是我们的属性"name"
,第二个参数'name'
表示我们正在打印的数据的类型,'name'
表示变量名。
此外,stylize
实际上是reaches this call,因为默认情况下stylizeWithColor
为真。
错误发生在ctx.colors
上的stylizeWithColor
。
function stylizeWithColor(str, styleType) {
var style = inspect.styles[styleType];
if (style) {
return `\u001b[${inspect.colors[style][0]}m${str}` + // <- ERROR: `inspect.colors[style][0]` becomes `undefined[0]`
`\u001b[${inspect.colors[style][1]}m`;
} else {
return str;
}
}
但为什么?
嗯,stylizeWithColor
的来电通过'name'
作为styleType
,但styleType
的唯一有效值是:
boolean
date
null
number
regexp
special
string
symbol
undefined
'name'
样式类型实际上是this line,因为变量名称是无格式的。
这些样式类型存储在普通对象ignored中,因此执行期望第一行上的inspect.styles['name']
返回undefined
(因为它被忽略)而不是输入{{1声明。
if
但是,由于// ...
var style = inspect.styles[styleType]; // <-- this should return `undefined`
if (style) { // <-- this shouldn't happen
// ...
只是一个POJO而我们在inspect.styles
上添加了"name"
属性,Object.prototype
没有直接找到inspect.styles['name']
但是确实找到了[[Prototype]]链并实际返回'name'
。
"bar"
这意味着代码会尝试执行// ...
var style = inspect.styles[styleType]; // <-- this returns "bar"` because it found it up the [[Prototype]] chain
if (style) { // <-- this happens because "bar" is truthy
// ...
,其中inspect.styles
是另一个POJO,其中包含颜色到inspect.colors
的映射,以便在终端中打印。正如人们所检查的那样,inspect.colors["bar"][0]
不是其中之一。
因此我们得到"bar"
,这会引发有问题的错误。
事实上,如果您使undefined[0]
等于name
中使用的颜色值,那么错误就不会发生,并且会打印属性inspect.colors
那种颜色。
编辑2:自pull request
起修复此问题