10

我收到了一个看起来像这样(非常简化)的文档的 ajax 提要:

aDocs = [{title:'new doc', ext:'pdf'}, {title:'another', ext:'xlsx'}];

我将遍历 aDocs 数组并显示有关每个文档的信息,同时向每个文档添加一些方法,这些方法将允许修改 HTML 以进行显示并进行 API 调用以更新数据库。

我在这里读到,为了向现有对象添加方法,您可以使用该__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
}

根据上面那篇文章,这不是官方的 javascript,IE 不支持(永远不会),并且可能会在 webkit 浏览器中被弃用。

这是一个替代方案:

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;
}

这第二种选择是否可行且有效?还是我重新创建了这些功能,从而产生了多余的开销?

再次简化了上面的例子(我知道aDocs[i].ext会解决上面的问题,但是我的显示和 API 调用方法更复杂)。

4

3 回答 3

8

这第二种选择是否可行且有效?

是的。

还是我重新创建了这些功能,从而产生了多余的开销?

不,这些功能是重复使用的,而不是重新创建的。所有对象都将共享和函数的单个副本。在从 (say) 调用函数期间,在调用中,将引用函数附加到的对象。(这仅适用于您将其作为从对象中检索它的表达式的一部分来调用,例如,)getExtgetTitleaDocs[1]thisvar title = aDocs[1].getTitle();

或者,如果您愿意,您可以创建共享原型的新对象,并将属性从aDocs对象复制到新对象,但是您已经询问了如何将新功能分配给现有对象,所以...

于 2013-03-12T16:55:20.103 回答
2

增加(添加方法到)原型通常是最好的方法,但是由于您正在处理对象文字(或 JSON.parse 结果),您必须要么增加Object.prototypewhich is not done,要么创建一个包装器构造函数,您需要将方法附加到其原型。问题将是: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'}

已经发布了许多更深入地处理这个问题的问题(和答案),所以如果你有兴趣:

javascript 中的对象和函数在
使用 John Resig 的 JavaScript 类继承实现时打印子类名称而不是“类”
是什么让 my.class.js 如此之快?
JavaScript 中这三种“类”定义模式之间有什么区别?

都或多或少与您的问题有关

于 2013-03-12T17:03:27.910 回答
1

在这种情况下,我只是将对象传递给 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]));
}

你的方法有两个问题:

  • 您必须为每个实例单独复制每个方法。
  • 您的“类”没有在任何地方记录,使其成为一个类可以更清楚地表明您的对象具有这些方法。
于 2013-03-12T16:58:49.850 回答