Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/432.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如果我定义了;名称“;具有Object.defineProperty()的属性_Javascript_Node.js - Fatal编程技术网

Javascript 如果我定义了;名称“;具有Object.defineProperty()的属性

Javascript 如果我定义了;名称“;具有Object.defineProperty()的属性,javascript,node.js,Javascript,Node.js,我已将代码缩减到最低限度: var util = require('util'); function ErrorDecorator(error) { Error.call(this); this.error = error; } util.inherits(ErrorDecorator, Error); Object.defineProperty(ErrorDecorator.prototype, 'name', { configurable: false,

我已将代码缩减到最低限度:

var util = require('util');

function ErrorDecorator(error) {
    Error.call(this);
    this.error = error;
}

util.inherits(ErrorDecorator, Error);

Object.defineProperty(ErrorDecorator.prototype, 'name', {
    configurable: false,
    enumerable: true,
    get: function () {
        return this.error.name;
    }
});

var e = new ErrorDecorator(new Error());

// TypeError: Cannot read property 'name' of undefined
console.log(e.toString());
编辑 我遇到过这样的情况,建议我在构造函数中使用
Object.defineProperty
,而不是在原型中使用。我不完全理解为什么,但我只能假设,当我在原型上定义
name
时,它被称为“静态的”,而不是以实例作为其上下文

TLDR此代码适用于:

var util = require('util');

function ErrorDecorator(error) {
    Error.call(this);
    this.error = error;
    Object.defineProperty(this, 'name', {
        configurable: false,
        enumerable: true,
        get: function () {
            return this.error.name;
        }
    });
}

util.inherits(ErrorDecorator, Error);

var e = new ErrorDecorator(new Error());

// Error
console.log(e.toString());
编辑2
即使我已经找到了一个解决方案,我仍然有兴趣知道为什么我的第一个代码示例不起作用,以及我所做的是否违背了最佳实践。

考虑以下几点:

var x = new Error();
var y = Object.create(x);
y.props = {
  name: 42
};
var z = Object.create(y);
Object.defineProperty(y, 'name', {
    configurable: false,
    enumerable: true,
    get: function () {
        console.log('Is it Z?', this === z);
        console.log('Is it Y?', this === y);
        return this.props.name;
    }
});
console.log(z.toString());
这很棘手:当对a)没有自己的
toString
实现且b)在其原型链中有
Error
实例的对象调用
toString
时,它遵循所描述的算法:

15.11.4.4 Error.prototype.toString()

采取以下步骤:

  • O
    设为
  • 如果
    类型(O)
    不是
    对象
    ,则抛出
    类型错误
    异常
  • name
    作为使用参数“name”调用
    [[Get]]
    O
    内部方法的结果
  • 如果
    名称
    未定义的
    ,则名称为“Error”;否则,将name设置为
    ToString(name)

问题在于,由于某种原因,当使用该getter时,nodejs(0.10.33)似乎在原型链上前进了一步:相应地,结果是
false
true
。Firefox和Chrome都正确地使用
z
作为getter上下文。

当您调用
console.log()
时,您确定
e
不是
未定义的
?在最后一行设置断点,并在应用程序中断时分析
e
。它已定义。这正是我用来重现错误的代码。在另一个
控制台之前运行
console.log(typeof e)
将显示
对象
。仅供参考:
console.log(e.name)
将按预期输出
错误
。@raina77现在我确信你正确完整地回答了我的问题,但我不明白。你是说
toString
被调用了不止一次,而且只有
ErrorDecorator
原型调用过一次吗?实际上不是。用
console.log('get')
替换
get
方法和
return 42
只会输出一次。感谢您花时间向我解释这一点。老实说,我一直想问node为什么会这样做,以及它是否在更新的版本中得到了修复——但这太过分了。我很高兴知道,
Error.prototype.toString
的NodeJSs实现中可能有一个bug,并且有一个解决方法,可以分别为每个实例定义属性。我使用的是0.10.40版。