在不为原型分配属性的情况下扩展Javascript对象

Extending a Javascript object without assigning properties to the prototype?

本文关键字:情况下 扩展 Javascript 对象 属性 原型 分配      更新时间:2023-09-26

我一直在尝试看看是否有一种方法可以绕过扩展对象的典型过程,从而表明它将扩展属性分配给对象的原型,但附加到当前对象上的"extend"方法本身。我希望直接在当前对象上分配属性(即"this.property"而不是"this.extend.property")。让我解释一下:

据我所知,有两种方法可以在Javascript中"扩展"对象:


1)全局函数:

function extend(a, b){
    for(var key in b)
        if(b.hasOwnProperty(key))
            a[key] = b[key];
    return a;
}

然后我可以运行此代码来"扩展"我的应用程序对象:

function App() {
    extend(this, {
        command: function () {
            alert('command!');
        }
    });
    console.log(this);
    return this;
}


2)另一种扩展方法是直接使用Object原型,即:

Object.prototype.extend = function(obj) {
   for(i in obj)
      this[i] = obj[i];
};

然后用扩展应用程序

function App() {
    this.extend({
        command: function () {
            alert('command!');
        }
    });
    console.log(this);
    return this;
}


然而,尽管在上述任何一种情况下,"命令"函数现在都可以在应用程序对象上访问,但这两种情况仍然表明,命令函数是应用程序原型中"扩展"方法的扩展。这两个控制台的输出都显示:(为简洁起见,隐藏其他应用程序属性):

command: function () {
    arguments: null, 
    caller: null, 
    length: 0, 
    name: "", 
    prototype: App.extend.command
}

注意到"应用程序扩展命令"了吗?我想知道是否有任何方法可以扩展这些属性,使它们成为应用程序对象的DIRECT属性,这样原型就会显示:"prototype:App.command"。

如果我将属性直接分配给"这个",我可以实现这一点,比如:

function App() {
    this.command = function () {
        alert('command!');
    }
    console.log(this);
    return this;
}

哪个输出:

command: function () {
    arguments: null, 
    caller: null, 
    length: 0, 
    name: "", 
    prototype: App.command
}

然而,我不想对我的所有属性都使用"this.blah=function()"的格式。我宁愿使用前两个示例中所示的JSON属性列表来扩展当前对象。有没有这样做,这样我仍然可以保留我的"newable"函数声明?

我要补充的是,最好不要使用原型方法,因为这将向应用程序中的所有对象添加"extend"属性,这对某些对象来说是不可取的。

感谢阅读!

为了更清楚地了解情况,您应该检查您在Firefox中使用Firebug发布的所有三种方式。webkit控制台的输出与App.prototype无关,而是为设置command-属性而调用的所有函数的层次结构。在App.__proto__下找到的App.prototype。

使用您的方法1),您可以将对象b的所有属性设置为每个应用程序实例的自己的属性(=this)。这些道具和功能extend()成为应用程序原型的一部分。你可以看看:

console.log(App.prototype);
// or you create an instance of App and search for its prototype:
var myapp = new App(); console.log(Object.getPrototypeOf(myapp));

当您在应用程序构造函数中包含函数extend()时,您可以获得与以下方式完全相同的结果:

function App(b) {
    if (typeof b == 'object') for (var key in b) this[key] = b[key];
    console.log(this);
    // Aside: you don't need 'return this', it's done automatically when you use 'new App()'
}
var obj = {command: function () {alert('command!');}};
var myapp = new App(obj);

我更喜欢这种方法,因为只需将其作为参数传入,就可以很容易地确定哪个应用程序对象获得了什么属性。

只有通过您的方式,函数extend()才会成为App.prototype的属性,因为您明确定义了它。然后它继承到所有应用程序实例。