最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

prototype - Best Way to Add Methods to Existing Javascript Object - Stack Overflow

programmeradmin1浏览0评论

I am receiving an ajax feed of documents that looks something like this (much simplified):

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.

I read here that in order to add methods to existing objects, you can use the __proto__ attribute. Something along the lines of:

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.

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).

I am receiving an ajax feed of documents that looks something like this (much simplified):

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.

I read here that in order to add methods to existing objects, you can use the __proto__ attribute. Something along the lines of:

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.

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).

Share Improve this question edited May 23, 2017 at 12:17 CommunityBot 11 silver badge asked Mar 12, 2013 at 16:52 Eric H.Eric H. 7,0148 gold badges45 silver badges64 bronze badges 1
  • What is the problem with what you've tried? – Ruan Mendes Commented Mar 12, 2013 at 16:55
Add a comment  | 

3 Answers 3

Reset to default 8

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 single copy 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();)

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 existing objects, so...

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 either augment 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...

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 function to 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?

Are all more or less related to your question

In this case, I would just pass the object to the constructor of 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.
发布评论

评论列表(0)

  1. 暂无评论