向现有 Javascript 对象添加方法的最佳方式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15367316/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Best Way to Add Methods to Existing Javascript Object
提问by Eric H.
I am receiving an ajax feed of documents that looks something like this (much simplified):
我收到了一个文件的 ajax 提要,看起来像这样(大大简化了):
aDocs = [{title:'new doc', ext:'pdf'}, {title:'another', ext:'xlsx'}];
I am going to iterate through the aDocs array and display information about each doc, while adding some methods to each doc that will allow for modifying the HTML for display and making API calls to update the database.
我将遍历 aDocs 数组并显示有关每个文档的信息,同时向每个文档添加一些方法,这些方法将允许修改用于显示的 HTML 并进行 API 调用以更新数据库。
I read herethat in order to add methods to existing objects, you can use the __proto__
attribute. Something along the lines of:
我在这里读到为了向现有对象添加方法,您可以使用该__proto__
属性。类似的东西:
function Doc(){}
Doc.prototype.getExt = function(){return this.ext}
Doc.prototype.getTitle = function(){return this.title}
for (var i=0; i<aDocs.length; i++){
aDocs[i].__proto__ = Doc.prototype
}
According to that article above,this isn't official javascript, isn't supported by IE (never will be), and will likely be deprecated in webkit browsers.
根据上面的那篇文章,这不是官方的 javascript,不受 IE 支持(永远不会),并且可能会在 webkit 浏览器中被弃用。
Here's an alternative stab at it:
这是另一种尝试:
function getExt(){ return this.ext }
function getTitle(){return this.title}
for (var i=0; i<aDocs.length; i++){
aDocs[i].getExt = getExt;
aDocs[i].getTitle = getTitle;
}
Is this second alternative viable and efficient? Or am I re-creating those functions and thereby creating redundant overhead?
这第二种选择可行且有效吗?还是我重新创建了这些功能,从而产生了多余的开销?
Again the above examples are simplified (I know aDocs[i].ext
will solve the problem above, but my methods for display and API calls are more complicated).
再次简化了上面的示例(我知道aDocs[i].ext
可以解决上面的问题,但是我的显示和 API 调用方法更复杂)。
采纳答案by T.J. Crowder
Is this second alternative viable and efficient?
这第二种选择可行且有效吗?
Yes.
是的。
Or am I re-creating those functions and thereby creating redundant overhead?
还是我重新创建了这些功能,从而产生了多余的开销?
No, the functions are reused, not re-created. All of the objects will share the singlecopy of the getExt
and getTitle
functions. During the call to the functions from (say) aDocs[1]
, within the call, this
will refer to the object the function is attached to. (This only applies if you call it as part of an expression retrieving it from the object, e.g., var title = aDocs[1].getTitle();
)
不,这些功能是重用的,而不是重新创建的。所有对象将共享和函数的单个副本。在从 (say) 调用函数期间,在调用中,将引用函数所附加的对象。(这仅适用于您将其作为从对象中检索它的表达式的一部分来调用的情况,例如,)getExt
getTitle
aDocs[1]
this
var title = aDocs[1].getTitle();
Alternately, if you liked, you could create new objects which shared a prototype, and copy the properties from the aDocs
objects to the new objects, but you've asked about assigning new functions to existingobjects, so...
或者,如果您愿意,您可以创建共享原型的新对象,并将属性从aDocs
对象复制到新对象,但是您已经询问了将新功能分配给现有对象的问题,所以......
回答by Elias Van Ootegem
Augmenting (adding methods to) the prototype is often the best way to go, but since you're dealing with object literals (or JSON.parse results), you'd have to eitheraugment the Object.prototype
which is not done, or create a wrapper constructor, with the methods you need attached to its prototype. The problem will be: getting to grips with this
in that case... I'd leave things as they are: use the second approach: a simple loop will do just fine. Besides: prototype methods are (marginally) slower anyway...
增强(添加方法)的样机往往是最好的一段路要走,但因为你正在处理的对象的文字(或JSON.parse结果),你就必须要么充实到Object.prototype
这是没有这样做,或者创建一个包装构造函数,将您需要的方法附加到其原型。问题将是:this
在这种情况下处理......我会保持现状:使用第二种方法:一个简单的循环就可以了。此外:无论如何,原型方法(略微)较慢......
The function objects themselves are being created ASAP (if they are defined in the global namespace, they're created as soon as the script is parsed). By simply looping through those objects, and assigning a reference to any functionto each object, you're not creating additional functions at all.
Just try this:
正在尽快创建函数对象本身(如果它们是在全局命名空间中定义的,则在解析脚本后立即创建它们)。通过简单地遍历这些对象,并将对任何函数的引用分配给每个对象,您根本不会创建其他函数。
试试这个:
var someObj = {name:'someObj'},
anotherObj = {name: 'anotherObj'},
someFunction = function()
{
console.log(this);
};
someObj.func = someFunction;
anotherObj.func = someFunction;
//or, shorter
someObj.func = anotherObj.func = someFunction;
//therefore:
console.log(someObj.func === anotherObj.func);//logs true! there is only 1 function object
someObj.func();//logs {name: 'someObj'}
anotherObj.func();//logs: {name: 'anotherObj'}
There have been posted many questions (and answers) that deal with this matter more in-depth, so if you're interested:
已经发布了许多更深入地处理这个问题的问题(和答案),所以如果你有兴趣:
Objects and functions in javascript
Print subclass name instead of 'Class' when using John Resig's JavaScript Class inheritance implementation
What makes my.class.js so fast?
What are the differences between these three patterns of "class" definitions in JavaScript?
javascript 中的对象和函数
使用 John Resig 的 JavaScript 类继承实现时,打印子类名称而不是“类”
是什么让 my.class.js 如此之快?
JavaScript 中“类”定义的这三种模式有什么区别?
Are all more or less related to your question
都或多或少与你的问题有关
回答by Juan Mendes
In this case, I would just pass the object to the constructor of Doc;
在这种情况下,我只是将对象传递给 Doc 的构造函数;
function Doc(obj){
this.obj = obj;
}
Doc.prototype.getExt = function(){
return this.obj.ext;
}
Doc.prototype.getTitle = function(){
return this.obj.title;
}
var docs = [];
for (var i=0; i<aDocs.length; i++){
docs.push(new Doc(aDocs[i]));
}
There are two problems with your approach:
你的方法有两个问题:
- You have to copy each method individually for every instance.
- Your "class"is not documented anywhere, making it a class makes it clearer that your object has those methods.
- 您必须为每个实例单独复制每个方法。
- 您的“类”未在任何地方记录,使其成为类可以更清楚地表明您的对象具有这些方法。