问题
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