如何正确扩展 JS 对象

How can I extend properly a JS object?

本文关键字:对象 JS 扩展 何正确      更新时间:2023-09-26

假设我在一个名为 main.js 的文件中有这样的东西:

function obj_name() {}
obj_name.prototype = {
    foo  : function() { alert('hi!'); },
    foo2 : function() { alert('hi again!'); }
}

现在我正在尝试以这种方式扩展另一个文件中的对象extend.js

obj_name.prototype = {
    newfoo : function() { alert('hi #3'); }
}

。但问题是,如果我这样编码,它就会起作用:

obj_name.prototype.newfoo = function() { alert('hi #3'); }

我想这可能是一个菜鸟问题。我什至不知道这是否是扩展对象的正确方法,但我在这里很害怕,想知道为什么会发生这种情况。

提前谢谢你们。

另一个没有jQuery的选项:

var extend = function(destination, source)
{
    for (var property in source)
    {
        if (destination[property] && (typeof(destination[property]) == 'object')
                && (destination[property].toString() == '[object Object]') && source[property])
            extend(destination[property], source[property]);
        else
            destination[property] = source[property];
    }
    return destination;
}
var a = {a: 'test'};                              // original
var b = {newFoo: function() { alert('hi #3'); }}; // the addition
extend(a, b);                                 // extend it
a.newFoo();                                   // call the added property

这是因为在行上

obj_name.prototype = {
    newfoo : function() { alert('hi #3'); }
}

创建新的原型对象,删除权限内容。就好像你说过

var a = {};

当您扩展对象时,例如

obj_name.prototype.newfoo = function() { alert('hi #3'); }

它只是在对象树中添加一个新属性(newfoo),保持现有内容不变。这就是它工作的原因

沃·斯托伊科夫

在第一种方式中,您将原型替换为新原型(覆盖以前存在的内容)。第二种方式,您将一个新成员添加到原型(从而扩展它)。

还有另一种方法:具有extend方法或类似方法的库(它基本上将您在第二种形式中正在做的事情包装在一个漂亮的包装器中)。例如,在jQuery中:

$.extend(obj_name.prototype, {
    newfoo : function() { alert('hi #3'); }
}

如果你正在寻找一个简单的轻量级库,它能给你这个:在javascript中,OOP"done right",看看这个: https://github.com/haroldiedema/joii

github 页面上的自述文件中提供的源代码示例,以及以下链接:

  • http://harold.info/projects/joii
  • http://haroldiedema.github.io/joii

这个库基本上允许你这样定义"类":

var Person = Class(function() {
    this.firstname = "John"
    this.surname   = "Smith"
    this.role= "Developer"
    this.getInfo = function() {
        return this.firstname + ' ' + this.surname + ' is ' + this.role;
    };
});
var AnotherPerson = Class({ extends: Person }, function() {
    this.firstname = "Bob";
});
var p = new AnotherPerson();
console.log(p.getInfo());
// Bob Smith is Developer

编辑

以您的代码为例,但转换为与 JOII 兼容的代码,它看起来像这样:

var obj_name = Class(function() {
    this.foo = function() { alert('hi!'); };
    this.foo2 = function() { alert('hi again!'); };
};
var obj_name2 = Class({ extends: obj_name }, function() {
    this.newfoo = function() { alert('hi #3'); };
});
var o = new obj_name2();
o.foo(); // hi!
o.newfoo(); // hi #3

或者将其用作混入:

var o = new obj_name();
o.mixin(obj_name2);
o.newfoo(); // hi #3

或者反过来,使用"特征"。

// the "uses" option basically copies content from the given object to the scope of your "class", solving the horizontal code-reuse problem.
var obj_name = Class({ uses: [obj_name2], function() {
    this.foo = function() { alert('hi!'); };
    this.foo2 = function() { alert('hi again!'); };
});
var o = new obj_name();
o.newfoo(); // hi #3