How can I extend properly a JS object?

孤街浪徒 提交于 2019-12-07 11:34:32

问题


Let's say I have something like this in a file named main.js:

function obj_name() {}

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

Now I am trying this way to expand the object in another file extend.js:

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

... but the problem is that it will just work if I code it this way:

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

I guess this may be a noob question. I don't even know if this is the proper way to extend an object, but I am freaking out here wondering why does this happen.

Thank you guys in advance.


回答1:


In the first way, you are replacing the prototype with a new one (overwriting what was there before). In the second way, you are adding a new member to the prototype (thus expanding it).

There is another method: a library that has an extend method or similar (which basically wraps what you're doing in your second form in a nice wrapper). For example, in jQuery:

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



回答2:


Another option without 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



回答3:


This is because on the row

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

you create a new prototype object, deleting privous contents. It is as if you've said

var a = {};

when you extend object like

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

it just add a new property (newfoo ) to the object tree keeping existing contents untouched. This is why it works

HTH

Ivo Stoykov




回答4:


If you're looking for a simple lightweight library that gives you exactly this: OOP "done right" in javascript, have a look at this: https://github.com/haroldiedema/joii

Source code examples provided in the readme on the github page, as well as these links:

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

This library basically allows you to define "classes" as such:

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

Edit

To take your code as an example but transformed into JOII-compatible code, it would look exactly like this:

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

Or use it as a mix-in:

var o = new obj_name();
o.mixin(obj_name2);

o.newfoo(); // hi #3

Or the other way around, using a "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


来源:https://stackoverflow.com/questions/5975408/how-can-i-extend-properly-a-js-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!