如何正确扩展JS对象?

时间:2011-05-12 08:36:43

标签: javascript javascript-objects

假设我在名为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'); }

我想这可能是一个菜鸟问题。我甚至不知道这是否是扩展对象的正确方法,但我在这里吓到了,想知道为什么会这样。

提前谢谢你们。

4 个答案:

答案 0 :(得分:6)

没有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

答案 1 :(得分:5)

这是因为在行

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

您创建一个新的原型对象,删除相关内容。就像你说的那样

var a = {};

扩展像

这样的对象时
obj_name.prototype.newfoo = function() { alert('hi #3'); }

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

HTH

Ivo Stoykov

答案 2 :(得分:4)

在第一种方式中,您将用新的原型替换原型(覆盖之前的原型)。在第二种方式中,您将向原型添加一个新成员(从而扩展它)。

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

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

答案 3 :(得分:1)

如果您正在寻找一个简单的轻量级库,它可以为您提供:OOP"正确完成"在javascript中,看看这个:https://github.com/haroldiedema/joii

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

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

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

或者相反,使用" trait"。

// 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