F = function(args) { Do something; return results; }is any function, and g = F(args) just means g = results. But consider
g = new F(args);The new (sort of) changes F into a new function, say newF:
newF = function(args,this) { Do something; return this; }where this is a new object created by the call. Note the results don't get passed to g, but the object this does. Thus the 'doing' is useful if is does things to this, e.g., add members:
F = function(i) { this.x = 99; this.y = i; return i*i; }so that
newF = function(i,this) { this.x = 99; this.y = i; return this; }Then g = new F(3) yields an object with two components:
g.x --> 99 g.y --> 3
F.prototype.constructor --> function F(i) { this.x = 99; this.y = i; return(i*i); }With g = new F(3), g gets assigned F.prototype as its prototype, which means the members of F.prototype are (overridable) members of g, though not members of g.prototype:
g.prototype --> undefined g.constructor --> function F(i) { this.x = 99; this.y = i; return(i*i); } g.x --> 99 g.y --> 3Now F can add members to its prototype, and these will carry over to g's prototype:
F.prototype = {b : 9, c : 17}; g = new F(3); g.b --> 9 g.c --> 17[This time, g.constructor --> function Object() { [native code] }.(‽))] The cool thing is now g is known to be an F:
g instanceof F --> trueNote: It doesn't seem to make sense to have a function be used both as a regular function and as a constructor. Calling the straight F(8) will still have to deal with the this object. Since it's not being passed to the function, it is a global this, which is the window object:
window.x and window.y --> undefined undefined F(8) --> 64 window.x and window.y --> 99 8Moral: A function should either be used the regular way, or be newed. Not both.
baseobject = {a: 7, b: 8, c: function() {return(this.a+this.b)}}then we'd have the template
--- Template --- function NewClass(i) { this.d = 3; this.a = i; } NewClass.prototype = baseobject; --- /Template ---Then instantiation and check:
nc = new NewClass(88): nc.a --> 88, nc.b --> 8, nc.c() --> 96, nc.d --> 3 (nc instanceof NewClass) --> true
--- Template --- function NewClass(){}; function createNewClass(i) { NewClass.prototype = baseobject; var f = new NewClass(); f.d = 3; if(i) f.a = i; return(f); } --- /Template ---Then instantiation and check:
nc = createNewClass(88): nc.a --> 88, nc.b --> 8, nc.c() --> 96, nc.d --> 3 (nc instanceof NewClass) --> true
It looks like the first way is a little easier. You don't need to remember to do as much: Just provide a constructor, and if needed set the prototype.
function DerivedClass(j) { this.b = j; } DerivedClass.prototype = new NewClass(17); dc = new DerivedClass(13): dc.a --> 17, dc.b --> 13, dc.c() --> 30, dc.d --> 3This new derived class instance is both a NewClass and a DerivedClass, as desired:
(dc instanceof DerivedClass) --> true (dc instanceof NewClass) --> trueThat seemed to work ok. I wonder if I can call the NewClass constructor from the DerivedClass. Yes. Use NewClass.call(this,args).
function Simple(str) { if(str!=undefined) {this.x[0] = str;this.y = 4;} } Simple.prototype = {x:[9], y:3}; var t = new Simple(): t.x[0] -->9, t.y --> 3 var s = new Simple("Kafka"); s.y = 4; s: s.x[0] --> "Kafka", s.y --> 4 t: t.x[0] --> "Kafka", t.y --> 3What happened? First, t was declared to be a Simple object with the default members values x[0] = 9 and y = 3.
Then s is defined to be another Simple object, but changes the defaults to x[0] = "Kafka" and y = 4.
But now t has changed: The x[0] has been changed to "Kafka", but y stays at 3.
The x component is an array. If an element in the array is changed, then it is changed for the prototype and all descendants. The component y is just a number, so changing it in s doesn't affect the other object t, nor the base object. But, changing x[0] in x changes it everywhere.
But if we assign a new array to x in the constructor, then it works the way we expected:
function Simple(str) { this.x = [9]; if(str!=undefined) {this.x[0] = str;} } Simple.prototype = {x:[],y:3}; var t = new Simple(): t.x[0] -->9, t.y --> 3 var s = new Simple("Kafka"); s.y = 4; s: s.x[0] --> "Kafka", s.y --> 4 t: t.x[0] --> 9, t.y --> 3The first approach didn't change the reference to the array x. The second did. So better be sure to give any arrays new references in the constructor (if that's the goal).