简体   繁体   English

节点REPL中的TypeError:当我向Object.prototype添加属性时,无法读取未定义的属性“ 0”

[英]TypeError in Node REPL: Cannot read property '0' of undefined when I add a property to the Object.prototype

When I added the name property to Object.prototype and reference Object.prototype , I get the following error: 当我将name属性添加到Object.prototype并引用Object.prototype ,出现以下错误:

TypeError: Cannot read property '0' of undefined"

But I can read Object.prototype.name . 但是我可以阅读Object.prototype.name Is the name property something special for Object.prototype ? name属性对Object.prototype是否特别? Why does this error occur? 为什么会发生此错误?

The code has been executed in Node v6.9.5 environment on Mac OS X. Does anyone know how to solve this? 该代码已在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)

After some inspection I found the culprit and yes, the problem is that "name" is used in a special way. 经过一番检查,我发现了罪魁祸首,是的,问题在于"name"是以一种特殊的方式使用的。

This error has nothing to do with JavaScript, it is a bug in the Node REPL code that styles the output. 此错误与JavaScript无关,这是在节点REPL代码中设置输出样式的错误。

Since we're printing an object, the code ends up executing this function : 由于我们正在打印对象,因此代码最终将执行以下功能

function formatObject(ctx, value, recurseTimes, visibleKeys, keys) {
  return keys.map(function(key) {
    return formatProperty(ctx, value, recurseTimes, visibleKeys, key, false);
  });
}

Where value is our Object.prototype , ie { name: 'bar' } and keys is an array of single element, ie ["name"] . 其中value是我们的Object.prototype ,即{ name: 'bar' }keys是单个元素的数组,即["name"]

For this single key "name" , execution continues to formatProperty , where it skips the checks to format objects with getters/setters or symbols and reaches a call to formatValue on this line . 对于此单个键"name" ,执行继续到formatProperty ,在此它跳过检查以使用getter / setter或符号格式化对象,并在此行上调用formatValue This call returns a color-coded representation of the value we should print, in our case something like "[32m'bar'[39m" . 该调用返回将要打印的值的颜色编码表示形式,在本例中为"[32m'bar'[39m"

Next, the code tries to build a string to display the context being printed. 接下来,代码尝试构建一个字符串以显示要打印的上下文。 This is the string corresponding to the type of the data being printed, for example [Object] , [Getter] , etc. The execution reaches this call : 这是与要打印的数据类型相对应的字符串,例如[Object][Getter]等。执行到达此调用

ctx.stylize(name, 'name');

The first argument name is our property "name" and the second argument 'name' represents the type of the data we are printing, 'name' meaning variable name. 第一个参数name是我们的属性"name" ,第二个参数'name'代表我们正在打印的数据类型, 'name'表示变量名称。

Further, stylize is actually stylizeWithColor since ctx.colors is true by default. 此外,由于ctx.colors默认为true,因此ctx.colors stylize实际上是stylizeWithColor

The error happens in stylizeWithColor on this line . 上的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;
  }
}

But why? 但为什么?

Well, the call to stylizeWithColor passes 'name' as the styleType , but the only valid values for styleType are: 那么,调用stylizeWithColor通过'name'作为styleType ,但唯一有效的值styleType是:

boolean
date
null
number
regexp
special
string
symbol
undefined

'name' style type is actually ignored as variable names are meant to be unstyled. 实际上, 'name'样式类型会被忽略,因为变量名称是无样式的。

These style types are stored in a plain object inspect.styles so the execution expects inspect.styles['name'] on the first line to return undefined (since it is ignored) and not enter the if statement. 这些样式类型存储在一个普通对象inspect.styles因此执行期望第一行的inspect.styles['name']返回undefined (因为它被忽略了)并且不输入if语句。

// ...

var style = inspect.styles[styleType]; // <-- this should return `undefined`

if (style) { // <-- this shouldn't happen

// ...

However, since inspect.styles is just a POJO and we added a "name" property on Object.prototype , inspect.styles['name'] doesn't find 'name' directly but does find it up the [[Prototype]] chain and actually returns "bar" . 但是,由于inspect.styles只是一个POJO,并且我们在Object.prototype上添加了"name"属性, Object.prototype inspect.styles['name']不会直接找到'name' ,而是会在[[Prototype]]上找到它链并实际上返回"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

// ...

This means that the code tries to execute inspect.colors["bar"][0] , where inspect.colors is another POJO containing a mapping of colors to their escaped code values for printing in the terminal. 这意味着代码尝试执行inspect.colors["bar"][0] ,其中inspect.colors是另一个POJO,其中包含颜色到其转义代码值的映射以在终端中打印。 As one would inspect, "bar" is not one of them. 正如人们所检查的那样, "bar"不是其中之一。

Hence we get undefined[0] , which throws the error in question. 因此,我们得到undefined[0] ,这引发了问题。

As a matter of fact, if you make name equal to a color value used in inspect.colors , then the error wouldn't happen and the property name will be printed in that color. 实际上,如果使name等于inspect.colors使用的颜色值,则不会发生错误,并且属性name将以该颜色打印。

节点彩色打印


Edit: I opened a pull request that fixes this problem by making inspect.styles a prototype-less object. 编辑:我打开了一个拉请求 ,通过使inspect.styles成为没有原型的对象来解决此问题。

Edit 2: This has been fixed as of Node 8 编辑2:自节点8起已修复

您应该尝试这样:

  Object.getOwnPropertyNames(Object);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Uncaught TypeError:无法读取未定义的属性“ prototype” - Uncaught TypeError: Cannot read property 'prototype' of undefined Reactjs - × TypeError:无法读取未定义的属性“原型” - Reactjs - × TypeError: Cannot read property 'prototype' of undefined 业力:TypeError:无法读取未定义的属性“ prototype” - karma: TypeError: Cannot read property 'prototype' of undefined 未捕获的TypeError:无法读取未定义的属性“ prototype” - Uncaught TypeError : cannot read property 'prototype' of undefined TypeError:无法读取未定义的属性“ prototype” - TypeError: Cannot read property 'prototype' of undefined TypeError:无法读取未定义 REACT 的属性“原型” - TypeError: Cannot read property 'prototype' of undefined REACT 如何在不将属性应用于Number.prototype的情况下将其添加到Object.prototype? - How can I add a property to Object.prototype without it being applied to Number.prototype? 节点:TypeError:无法读取未定义的属性“ on” - Node: TypeError: Cannot read property 'on' of undefined 节点:TypeError:无法读取未定义的属性“替换” - Node: TypeError: Cannot read property 'replace' of undefined 类型错误:无法读取未定义的属性“节点” - TypeError: Cannot read property 'node' of undefined
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM