gpt4 book ai didi

javascript - 对象可以*真正*从Error.prototype继承吗?

转载 作者:行者123 更新时间:2023-12-03 16:41:41 29 4
gpt4 key购买 nike

[关于此主题还有其他类似的问题,但是它们都没有回答我在这里提出的问题,即AFAICT。 (即,我已经阅读了所有答案,解释了为什么特定构造无法与发问者尝试进行的操作,在某些情况下,它们提供了获得所需结果的替代方法。但是没有线程可以回答如何实现真正继承的问题。来自Error.prototype。)]

我设法做到的最好基本上还是没用:

function MyErr(message) {
var tmp = Error.apply(this, arguments);
for (var prop in tmp) { this[prop] = tmp[prop]; }
}
MyErr.prototype = Object.create(Error.prototype);

即使在“手动”复制属性(肯定是“无效继承”的标志)之后, new MyErr("whatever")返回的对象仍然是 ,甚至没有远程关闭到我认为的“从 Error.prototype继承的实例”。与预期行为的偏差确实太多,无法在此处列出-在我所看到的所有位置都会弹出!-但是,对于初学者而言,
console.log((new Error("some error")).toString())     // "Error: some error"
console.log((new MyErr("another error")).toString()) // "Error"
// expected
// "MyError: another error"

console.log((new Error("some error")).constructor) // "Error()"
console.log((new MyErr("another error")).constructor) // "Error()"
// expected:
// "MyError()"

(如果有人怀疑,不, constructor并不是在 MyErrfor循环中复制的属性之一。我检查过。)

对象 可以从Error.prototype真正继承吗?

鉴于要回答 Array的类似问题需要 a lengthy treatise,我在这里不能合理地期望对我的问题有完整的答案,但是我希望我能找到指向这样的完整答案的指针。

更新:我尝试了Bergi的建议。下面我提供了一个完整的,自包含的实现。1
<!DOCTYPE html>
<html><head><meta charset="utf-8"></head><body>
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script>
jQuery(document).ready(function ($) {
function MyErr(message) {
var tmp = Error.apply(this, arguments);
Object.getOwnPropertyNames(tmp).forEach(function(p) {
console.log('property: ' + p);
Object.defineProperty(this, p,
Object.getOwnPropertyDescriptor(tmp, p));
}, this);
console.log('done creating ' + this);
}
MyErr.prototype = Object.create(Error.prototype, {
constructor: {value:MyErr, configurable:true},
name: {value:"MyErr", configurable:true}
});

var error = new Error("some error");
var myerr = new MyErr("another error");

console.log(error.toString());
console.log(myerr.toString());

console.log(error.constructor);
console.log(myerr.constructor);
});
</script></body></html>

我在Firebug控制台中得到的输出是这样的:
done creating MyErr                                         testjs.html (line 13)
Error: some error testjs.html (line 23)
MyErr testjs.html (line 24)
Error() testjs.html (line 26)
MyErr(message) testjs.html (line 27)

特别注意,输出不包括以 property:开头的任何行。这意味着 console.logforEach循环内的 MyErr语句将永远不会执行(其余 forEach回调也可能执行同样的操作)。

如果我将 forEach循环替换为
        for (var p in tmp) {
console.log('property: ' + p);
Object.defineProperty(this, p,
Object.getOwnPropertyDescriptor(tmp, p));
};

...然后,在输出前添加了三行(省略了行号):
property: fileName
property: lineNumber
property: columnNumber

这表明 message属性中甚至没有 tmp(尽管 message确实显示在Firebug变量检查器中的 tmp的属性中,还有不计其数的其他属性也未显示在上面的控制台输出中)。

另外,显式设置的 name属性的确在 myerr.toString()的输出中出现,但是此方法的行为与 error.toString()相同。

如果我在 myerr.toString()函数的末尾添加以下行,则确实从 MyErr获得了预期的输出:
this.message = message;

...但是我对此一点都不感到安慰,因为这种操作以及我上面显示的大多数其他操作都是针对我发布的特定示例的临时克鲁格,但这些示例仅是为了举例说明似乎是一个更深层次的问题,即预期继承模型的完整分解。

这个问题的目的是找出如何从 Error.prototype实现“真正的继承”,如果不可能的话,则尽可能地对其进行仿真,以清楚地了解仿真在多大程度上无法实现该继承。完全继承模型。我强调,这两种选择中的后一种不应与每次我们偶然发现某种不符合预期的新方法时逐步修补一些有缺陷的实现的策略相混淆。这种“增量修补”方法为无声错误提供了理想的环境,因此是精神错乱的良方。

UPDATE2: JS的不可预测性似乎没有尽头。我刚刚发现,至少在Firebug控制台中, Object.getOwnPropertyNames生成不同的值,具体取决于其参数是非原子表达式还是先前已为其分配了相同非原子表达式的变量。 wtf?

例如,以下内容是直接从Firebug控制台中的交互复制粘贴的(为了便于阅读,我在每个命令前添加了一个空行):
>>> Object.getOwnPropertyNames(new Error("not assigned"))
[]

>>> errorvar = new Error("assigned")
Error: assigned
(no source for debugger eval code)

>>> Object.getOwnPropertyNames(errorvar)
["fileName", "lineNumber", "message", "stack"]

(分配给 errorvar之后的输出似乎与创建了 Error对象有关,即使它不是 throw n也是如此。即使在该行中删除了 new左侧的所有内容,也会出现相同的输出。 )

如果那还不够,我是否可以在脚本中运行
console.log(Object.getOwnPropertyNames(new Error("not assigned")))
var errorvar = new Error("assigned");
console.log(Object.getOwnPropertyNames(errorvar));

Firebug控制台中的输出为
[ ]
[ ]

我不知道这种错误的行为是否是由于ECMAScript5,JavaScript,Firefox,Firebug或其他原因引起的,但是它使我发疯了……

1我发布了这个独立的实现,以鼓励其他人尝试一下。如果我了解到JavaScript的一件事是,无论代码多么简单,也不管您对JavaScript有多少了解,知道某些JavaScript代码将要做什么的唯一方法就是运行它。可悲的是,JavaScript编程仍然是一个令人尴尬的实验 Activity 。 JS不适合扶手椅程序员! :)

最佳答案

好吧,除了堆栈跟踪和instanceof,我不知道您还需要什么。试试这个:

function MyError(message) {
this.name = this.constructor.name;
this.message = message;
if (Error.captureStackTrace) {
Error.captureStackTrace(this, this.constructor);
} else {
var stack = new Error().stack;
if (typeof stack === "string") {
stack = stack.split("\n");
stack.shift();
this.stack = stack.join("\n");
}
}
}
MyError.prototype = Object.create(Error.prototype, {
constructor: {
value: MyError,
writable: true,
configurable: true
}
});
try {
throw new MyError("message");
} catch (e) {
console.log(e + "");
console.log(e.stack + "");
}
try {
throw new Error("message");
} catch (e) {
console.log(e + "");
console.log(e.stack + "");
}

http://jsfiddle.net/VjAC7/1/

Chrome
MyError: message
MyError: message
at window.onload (http://fiddle.jshell.net/VjAC7/1/show/:44:11)
Error: message
Error: message
at window.onload (http://fiddle.jshell.net/VjAC7/1/show/:51:11)

火狐浏览器
MyError: message
window.onload@http://fiddle.jshell.net/VjAC7/1/show/:44
Error: message
window.onload@http://fiddle.jshell.net/VjAC7/1/show/:51

IE10
Error: message 
Error: message
at onload (http://fiddle.jshell.net/VjAC7/1/show/:44:5)
Error: message
Error: message
at onload (http://fiddle.jshell.net/VjAC7/1/show/:51:5)

关于javascript - 对象可以*真正*从Error.prototype继承吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18943507/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com