增加 Object.prototype 破坏道场
Augmenting Object.prototype breaks Dojo
我遇到了一个问题,它可能是错误,也可能只是预期的功能。我正在使用使用 Dojo 构建的第三方脚本。在我自己的应用程序中,我增加了 Function.prototype 和 Object.prototype (对于我的应用程序)方便的实用程序功能。包含第三方脚本总是导致错误。
Uncaught TypeError: Cannot set property _scopeName' of undefined
Uncaught TypeError: Cannot read property 'toString' of undefined
过了一会儿我意识到这可能在于我增强了这些原型。 Function.prototypes 似乎没有不良影响。但是,一旦我删除了所有 Object.prototype 方法,它就停止抛出错误。
一个简单的测试设置
<html lang="nl">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script>
Object.prototype.foo = function() {
console.log('bar');
}
</script>
<script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js"></script>
</body>
</html>
这是故意的吗?如果是这样,那么捕获这个错误并抛出一个更有意义的错误不是更好吗?
不要那样做。 :-)
您已将可枚举的 属性 添加到 Object.prototype
,这意味着它显示在 所有对象 中(通过继承)在 for-in
循环等等:
// DON'T DO THIS (see text for why)
Object.prototype.foo = function() {
console.log("foo");
};
// Looping over an object
var obj = {
myOwnProperty: "bar"
};
for (var key in obj) {
snippet.log("obj['" + key + "']: " + obj[key]);
}
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
请注意 foo
出现在我们的循环中。现在,通常您会希望在 for-in
循环中进行 hasOwnProperty
检查,但有时您不需要;将可枚举属性添加到 Object.prototype
打破了 hasOwnProperty
不合适的情况。
将任何东西添加到Object.prototype
通常被认为是一个非常糟糕的主意。强烈建议完全不要这样做。
但是,如果您有可靠的用例,请使用 非常独特的名称 定义 属性 并使其不可枚举:
Object.defineProperty(Object.prototype, "veryDistinctName", {
value: function() {
console.log("veryDistinctName");
}
});
defineProperty
定义的属性在默认情况下是不可枚举的(默认情况下也是只读的),因此 veryDistinctName
不会出现在 for-in
循环中,例如:
// *IF* you absolutely, positively *have* to define a new
// property on Object.prototype, make it non-enumerable:
Object.defineProperty(Object.prototype, "veryDistinctName", {
value: function() {
console.log("veryDistinctName");
}
});
// Looping over an object
var obj = {
myOwnProperty: "bar"
};
for (var key in obj) {
snippet.log("obj['" + key + "']: " + obj[key]);
}
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
如您所见,veryDistinctName
没有显示在循环中。
Is this intended?
可能不明确,不。他们只是假设你不会增加 Object.prototype
.
And if so, would it not be better to then catch this error and throw a more meaningfull one?
这是一个见仁见智的问题,但是:可能不是,它有很多额外的开销,却收效甚微。一般来说,人们知道不增加Object.prototype
。如果你这样做,那么很多事情都会很快崩溃,你很快就会学会不去做。所以迎合这种情况可能有点矫枉过正。
就是说,当 loading/initializing 库时,我可以看到一个检查的参数:
for (var key in {}) {
throw new Error("Enumerable property '" + key + "' found on Object.prototype. Dojo doesn't support enumerable Object.prototype properties.");
}
当然,您仍然可以通过添加到 Object.prototype
稍后 来打破它。
我遇到了一个问题,它可能是错误,也可能只是预期的功能。我正在使用使用 Dojo 构建的第三方脚本。在我自己的应用程序中,我增加了 Function.prototype 和 Object.prototype (对于我的应用程序)方便的实用程序功能。包含第三方脚本总是导致错误。
Uncaught TypeError: Cannot set property _scopeName' of undefined
Uncaught TypeError: Cannot read property 'toString' of undefined
过了一会儿我意识到这可能在于我增强了这些原型。 Function.prototypes 似乎没有不良影响。但是,一旦我删除了所有 Object.prototype 方法,它就停止抛出错误。
一个简单的测试设置
<html lang="nl">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script>
Object.prototype.foo = function() {
console.log('bar');
}
</script>
<script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js"></script>
</body>
</html>
这是故意的吗?如果是这样,那么捕获这个错误并抛出一个更有意义的错误不是更好吗?
不要那样做。 :-)
您已将可枚举的 属性 添加到 Object.prototype
,这意味着它显示在 所有对象 中(通过继承)在 for-in
循环等等:
// DON'T DO THIS (see text for why)
Object.prototype.foo = function() {
console.log("foo");
};
// Looping over an object
var obj = {
myOwnProperty: "bar"
};
for (var key in obj) {
snippet.log("obj['" + key + "']: " + obj[key]);
}
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
请注意 foo
出现在我们的循环中。现在,通常您会希望在 for-in
循环中进行 hasOwnProperty
检查,但有时您不需要;将可枚举属性添加到 Object.prototype
打破了 hasOwnProperty
不合适的情况。
将任何东西添加到Object.prototype
通常被认为是一个非常糟糕的主意。强烈建议完全不要这样做。
但是,如果您有可靠的用例,请使用 非常独特的名称 定义 属性 并使其不可枚举:
Object.defineProperty(Object.prototype, "veryDistinctName", {
value: function() {
console.log("veryDistinctName");
}
});
defineProperty
定义的属性在默认情况下是不可枚举的(默认情况下也是只读的),因此 veryDistinctName
不会出现在 for-in
循环中,例如:
// *IF* you absolutely, positively *have* to define a new
// property on Object.prototype, make it non-enumerable:
Object.defineProperty(Object.prototype, "veryDistinctName", {
value: function() {
console.log("veryDistinctName");
}
});
// Looping over an object
var obj = {
myOwnProperty: "bar"
};
for (var key in obj) {
snippet.log("obj['" + key + "']: " + obj[key]);
}
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
如您所见,veryDistinctName
没有显示在循环中。
Is this intended?
可能不明确,不。他们只是假设你不会增加 Object.prototype
.
And if so, would it not be better to then catch this error and throw a more meaningfull one?
这是一个见仁见智的问题,但是:可能不是,它有很多额外的开销,却收效甚微。一般来说,人们知道不增加Object.prototype
。如果你这样做,那么很多事情都会很快崩溃,你很快就会学会不去做。所以迎合这种情况可能有点矫枉过正。
就是说,当 loading/initializing 库时,我可以看到一个检查的参数:
for (var key in {}) {
throw new Error("Enumerable property '" + key + "' found on Object.prototype. Dojo doesn't support enumerable Object.prototype properties.");
}
当然,您仍然可以通过添加到 Object.prototype
稍后 来打破它。