【问题标题】:Best Way to Add Methods to Existing Javascript Object向现有 Javascript 对象添加方法的最佳方式
【发布时间】:2013-03-12 16:52:36
【问题描述】:

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

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

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

我读过here ,为了向现有对象添加方法,您可以使用__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调用更复杂)。

【问题讨论】:

  • 你试过的有什么问题?

标签: javascript prototype


【解决方案1】:

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

是的。

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

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

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

【讨论】:

    【解决方案2】:

    扩充(添加方法到)原型通常是最好的方法,但由于您处理的是对象字面量(或 JSON.parse 结果),您必须或者扩充Object.prototype 未完成,或者创建一个包装构造函数,将您需要的方法附加到其原型。问题将是:在这种情况下掌握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'}
    

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

    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?

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

    【讨论】:

    • 感谢您的回答和资源。我给了 TJ 答案 b/c 他早先得到了答案,并在这里得到了所有的精髓。但是为额外资源 +1。
    【解决方案3】:

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

    你的方法有两个问题:

    • 您必须为每个实例单独复制每个方法。
    • 您的 "class" 没有在任何地方记录,将其设为类可以更清楚地表明您的对象具有这些方法。

    【讨论】:

      猜你喜欢
      • 2018-05-27
      • 2023-03-10
      • 1970-01-01
      • 2014-12-22
      • 1970-01-01
      相关资源
      最近更新 更多