- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
回顾:
好吧,自从我问这个问题以来已经有一段时间了。像往常一样,我还是去增强了 Object.prototype
,尽管这里和网络上其他地方都给出了反对它的所有有效论据。我想我就是那种顽固的 SCSS 。
我试图想出一种决定性的方法来防止新方法破坏任何预期的行为,事实证明这是一件非常困难但信息丰富的事情。
我学到了很多关于 JavaScript 的知识。至少我不会尝试任何像扰乱 native 原型(prototype)这样鲁莽的事情(除了 IE < 9 的 String.prototype.trim
)。
在这种特殊情况下,我不使用任何库,因此冲突不是我主要关心的问题。但是,在对使用 native 原型(prototype)时可能出现的问题进行了更深入的研究后,我不太可能尝试将此代码与任何库结合使用。
通过研究这种原型(prototype)方法,我对模型本身有了更好的理解。我将原型(prototype)视为某种形式的灵活的传统抽象类,这使我坚持传统的 OOP 思维。这种观点并没有真正公正地对待原型(prototype)模型。道格拉斯·克罗克福德(Douglas Crockford)写了关于这个陷阱的文章,遗憾的是粉红色的背景使我无法阅读全文。
我决定更新这个问题,以防阅读本文的人想亲自看看。我只能说:无论如何,一定要做。我希望你在决定放弃这个相当愚蠢的想法之前,能像我一样学到一些巧妙的东西。一个简单的函数可能同样有效,甚至更好,尤其是在这种情况下。毕竟,它的真正美妙之处在于,只需添加 3 行代码,您就可以使用相同的函数来增强特定对象的原型(prototype)。
<小时/>我知道我要问一个已经存在很长一段时间的问题,但是:为什么 Object.prototype 被认为是禁区?它就在那里,并且可以像任何其他原型(prototype)一样进行增强。那么,为什么你不应该利用这一点呢?在我看来,只要您知道自己在做什么,就没有理由避开对象原型(prototype)。
以此方法为例:
if (!Object.prototype.getProperties)
{
Object.prototype.getProperties = function(f)
{
"use strict";
var i,ret;
f = f || false;
ret = [];
for (i in this)
{
if (this.hasOwnProperty(i))
{
if (f === false && typeof this[i] === 'function')
{
continue;
}
ret.push(i);
}
}
return ret;
};
}
基本上,它与旧的 for...in
循环相同,您可以在函数中保持安全,或者一遍又一遍地编写。我知道它将被添加到所有对象中,并且由于JavaScript中几乎每个继承链都可以追溯到Object.prototype
,但在我的脚本中,我认为它两害相权取其轻。
也许,有人可以比 this chap 更好地告诉我哪里错了。等。
在寻找人们不触摸对象
原型(prototype)的原因时,一件事不断出现:它打破了for..in
循环事物,但话又说回来:许多框架也是如此,更不用说您自己的继承链了。因此,在我看来,在循环对象的属性时不包含 .hasOwnProperty
检查是不好的做法。
我还发现了this相当有趣。再说一次:有一个评论是相当明确的:扩展原生原型(prototype)是一种不好的做法,但如果 V8 的人这样做了,我有什么资格说他们错了呢?
我知道,这个论点不太成立。
重点是:我真的看不出上面的代码有什么问题。我喜欢它,经常使用它,到目前为止,它从未让我失望过。我什至正在考虑向对象原型(prototype)附加更多函数。除非有人能告诉我为什么我不应该这么做。
最佳答案
事实是,只要您知道自己在做什么以及成本是多少,就可以了。但这是一个很大的“如果”。一些成本示例:
您需要对您选择在增强 Object.prototype
的环境中使用的任何库进行广泛测试。 ,因为压倒性的约定是空白对象没有可枚举的属性。通过将可枚举属性添加到 Object.prototype
,你使该约定变得错误。例如,这很常见:
var obj = {"a": 1, "b": 2};
var name;
for (name in obj) {
console.log(name);
}
...压倒性的约定是仅显示“a”和“b”,而不显示“getProperties”。
任何编写代码的人都必须接受这样的教育:没有遵守该约定(上述)。
您可以使用 Object.defineProperty
来缓解上述问题(和类似的)如果支持的话,但要注意,即使在 2014 年,像 IE8 这样的浏览器 don't support it正确地保持重要使用(尽管我们希望 XP 正式停产后这种情况会很快改变)。那是因为使用 Object.defineProperty
,您可以添加不可枚举属性(那些不会出现在 for-in
循环中的属性),这样您就会少很多麻烦(此时,您主要担心名称冲突)——但它仅适用于正确实现 Object.defineProperty
的系统(并且正确的实现不能被“填充”)。
在您的示例中,我不会添加 getProperties
至Object.prototype
;我会将其添加到 Object
并接受该对象作为参数,就像 ES5 对 getPrototypeOf
所做的那样和类似的。
请注意,Prototype 库因扩展 Array.prototype
而受到很多批评。因为这会影响 for..in
循环。这只是 Array
s (无论如何你都不应该使用 for..in
(除非你使用 hasOwnProperty
保护并且很可能也使用 String(Number(name)) === name
)。
...if the V8 people do it, who am I to say they're wrong?
在 V8 上,您可以信赖 Object.defineProperty
,因为 V8 是一个完全兼容 ES5 的引擎。
请注意,即使属性是不可枚举的,也存在问题。多年前,Prototype(间接)定义了 filter
功能于 Array.prototype
。它执行您所期望的操作:调用迭代器函数并根据函数选择的元素创建一个新数组。然后 ECMAScript5 出现并定义了 Array.prototype.filter
做同样的事情。但有一个问题:很多都是同样的事情。特别是,被调用的迭代器函数的签名是不同的(ECMAScript5 包含一个 Prototype 没有的参数)。情况可能比这更糟糕(我怀疑 - 但无法证明 - TC39 知道 Prototype 并故意避免与它发生太多冲突)。
所以:如果您打算这样做,请注意风险和成本。由于尝试使用现成的库,您可能会遇到丑陋的边缘情况错误,这确实会浪费您的时间......
关于javascript - Object.prototype 被禁止?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10757455/
我遵循了一本名为“Sitepoint Full Stack Javascript with MEAN”的书中的教程,我刚刚完成了第 6 章,应该已经创建了一个带有“数据库”的“服务器”。数据库只不过是
在 Jquery 中,我创建两个数组,一个嵌入另一个数组,就像这样...... arrayOne = [{name:'a',value:1}, {name:'b',value:2}] var arra
这个问题在这里已经有了答案: What is the explanation for these bizarre JavaScript behaviours mentioned in the 'Wa
我被放在别人的代码上,有一个类用作其他组件的基础。当我尝试 ng serve --aot(或 build --prod)时,我得到以下信息。 @Component({ ...,
我正在测试一些代码,并使用数据创建了一个 json 文件。 问题是我在警报中收到“[object Object],[object Object]”。没有数据。 我做错了什么? 这是代码:
我想打印 [object Object],[object Object] 以明智地 "[[{ 'x': '1', 'y': '0' }, { 'x': '2', 'y': '1' }]]"; 在 ja
我有一个功能 View ,我正在尝试以特殊格式的方式输出。但我无法让列表功能正常工作。 我得到的唯一返回是[object Object][object Object] [object Object]
在使用优秀的 Sim.js 和 Three.js 库处理 WebGL 项目时,我偶然发现了下一个问题: 一路走来,它使用了 THREE.Ray 的下一个构造函数: var ray = new THRE
我正在使用 Material UI 进行多重选择。这是我的代码。 {listStates.map(col => (
我的代码使用ajax: $("#keyword").keyup(function() { var keyword = $("#keyword").val(); if (keyword.
我遇到了下一个错误,无法理解如何解决它。 Can't resolve all parameters for AuthenticationService: ([object Object], ?, [o
我正在尝试创建一个显示动态复选框的表单,至少应选中其中一个才能继续。我还需要获取一组选中的复选框。 这是组件的代码: import { Component, OnInit } from '@angul
我正在开发 NodeJs 应用程序,它是博客应用程序。我使用了快速验证器,我尝试在 UI 端使用快速闪存消息将帖子保存在数据库中之前使用闪存消息验证数据,我成功地将数据保存在数据库中,但在提交表单后消
我知道有些人问了同样的问题并得到了解答。我已经查看了所有这些,但仍然无法解决我的问题。我有一个 jquery snipet,它将值发送到处理程序,处理程序处理来自 JS 的值并将数据作为 JSON 数
我继承了一个非常草率的项目,我的任务是解释为什么它不好。我注意到他们在整个代码中都进行了这样的比较 (IQueryable).FirstOrDefault(x => x.Facility == fac
我只是在删除数组中的对象时偶然发现了这一点。 代码如下: friends = []; friends.push( { a: 'Nexus', b: 'Muffi
这两个代码片段有什么区别: object = nil; [object release] 对比 [object release]; object = nil; 哪个是最佳实践? 最佳答案 object
我应该为其他人将从中继承的第一个父对象传递哪个参数,哪个参数更有效 Object.create(Object.prototype) Object.create(Object) Object.creat
我在不同的对象上安排不同的选择器 [self performSelector:@selector(doSmth) withObject:objectA afterDelay:1]; [self per
NSLog(@"%p", &object); 和 NSLog(@"%p", object); 有什么区别? 两者似乎都打印出一个内存地址,但我不确定哪个是对象的实际内存地址。 最佳答案 这就是我喜欢的
我是一名优秀的程序员,十分优秀!