Javascript prototypal inheritance - descendants override each other - javascript

I'm creating two objects (Inherits), both inherit from Base.
The second object's property assignment overrides the value in the first object.
Any thoughts? How to make a proper inheritance so that Base class will contain common members for its inheritance descendants, but the descendants could assign values of their own without interfering each other.
var testParams1 = { title: "john" };
var testParams2 = { title: "mike" };
Function.prototype.inheritsFrom = function (baseClass)
{
this.prototype = new baseClass;
this.prototype.constructor = this;
this.prototype.base = baseClass.prototype;
return this;
};
function Base() {
this.viewModel = {};
this.viewModel.title = (function ()
{
var savedVal = "";
return function (newVal)
{
if (typeof (newVal) === "undefined")
{
return savedVal;
}
savedVal = newVal;
};
})();
}
function Inherits(params) {
this.viewModel.title(params.title);
}
Inherits.inheritsFrom(Base);
///// preparing code:
var testObj1 = new Inherits(testParams1);
var testObj2 = new Inherits(testParams2);
///// testing code:
equals(testObj1.viewModel.title(), testParams1.title, "first instance ok"); // returns "john"
equals(testObj2.viewModel.title(), testParams2.title, "second instance ok"); // also returns "john"

Problem(s)
The Base class constructor is called once and only once.
this.prototype = new baseClass;
Privileged methods will refer to the same this object across instances because those methods are created within the constructor (which was called only once).
Problem(s) based on a matter of opinion
You should try to avoid modifying native prototypes (ie. Function.prototype) if you plan on working alongside JavaScript that you do not own.
Solution
Call the constructor and parent constructor(s) for each new instance that is created.
Inherit the parent prototype chain (not a instance of a the parent class).
Maintain a 1:1 ratio of number of instances created to the number of calls the constructor(s) in the prototype chain.
Final solution to Max's problem
Please pay special attention to the inherits function and the ParentClass.call(this, title); line.
Constructors to look for are ParentClass and ChildClass
/**
* Allows a child constructor to safely inherit the parent constructors prototype chain.
* #type {Function}
* #param {!Function} childConstructor
* #param {!Function} parentConstructor
*/
function inherits(childConstructor, parentConstructor){
var TempConstructor = function(){};
TempConstructor.prototype = parentConstructor.prototype; // Inherit parent prototype chain
childConstructor.prototype = new TempConstructor(); // Create buffer object to prevent assignments directly to parent prototype reference.
childConstructor.prototype.constructor = childConstructor; // Reset the constructor property back the the child constructor
};
//////////////////////////////////////
/** #constructor */
function ParentClass(title) {
this.setTitle(title);
var randId_ = Math.random();
/** #return {number} */
this.getPrivlegedRandId = function()
{return randId_;};
};
/** #return {string} */
ParentClass.prototype.getTitle = function()
{return this.title_;};
/** #param {string} value */
ParentClass.prototype.setTitle = function(value)
{this.title_ = value;};
//////////////////////////////////////
/**
* #constructor
* #param {string} title
* #param {string} name
*/
ChildClass = function (name, title) {
ParentClass.call(this, title); // Call the parent class constructor with the required arguments
this.setName(name);
}
inherits(ChildClass, ParentClass); // Inherit the parent class prototype chain.
/** #return {string} */
ChildClass.prototype.getName = function()
{return this.name_;};
/** #param {string} value */
ChildClass.prototype.setName = function(value)
{this.name_ = value;};
Down the rabbit hole
For those who are curious why that works vs simply memorizing it the inherits function.
How properties are resolved using the prototype chain
When a property is not found at the instance level, JavaScript will try to resolve the missing property by searching through the instance constructors prototype chain. If the property is not found in the first prototype object, it will search the parent prototype object and so on all the way up to Object.prototype. If it can't find it within Object.prototype then an error will be thrown.
Calling the parent constructor from child constructor : Attempt #1
// Bad
var ChildConstructor = function(arg1, arg2, arg3){
var that = new ParentConstructor(this, arg1, arg2, arg3);
that.getArg1 = function(){return arg1};
return that;
}
Any varible that is created using new ChildConstructor will return an instance of ParentConstructor.
The ChildConstructor.prototype will be not be used.
Calling the parent constructor from child constructor : Attempt #2
// Good
var ChildConstructor = function(arg1, arg2, arg3){
ParentConstructor.call(this, arg1, arg2, arg3);
}
Now constructor and the parent constructor is called appropriately. However, only methods defined within the constructor(s) will exist. Properties on the parent prototypes will not be used because they have not yet been linked to the child constructors prototype.
Inheriting the parent prototype : Attempt #1
// Bad
ChildConstructor.prototype = new ParentConstructor();
The parent constructor will either be called only once or one too many times depending on whether or not ParentConstructor.call(this) is used.
Inheriting the parent prototype attempt #2
// Bad
ChildConstructor.prototype = ParentConstructor.prototype;
Though this technically works, any assignments to ChildConstructor.prototype will also be assigned to ParentConstructor.prototype because Objects are passed by reference and not by copy.
Inheriting the parent prototype attempt #3
// Almost there
var TempConstructor = function(){};
TempConstructor.prototype = ParentConstructor.prototype;
ChildConstructor.prototype = new TempConstructor();
This allows you to assign properties to ChildConstructor.prototype because it is an instance of a temporary anonymous function.
Properties that are not found on the instance of TempConstructor will then check it's prototype chain for the property, so you have successfully inherited the parent prototype. The only problem is that ChildConstructor.prototype.constructor is now pointing to TempConstructor.
Inheriting the parent prototype attempt #4
// Good
var TempConstructor = function(){};
TempConstructor.prototype = ParentConstructor.prototype;
ChildConstructor.prototype = new TempConstructor();
ChildConstructor.prototype.constructor = ChildConstructor;
All Together
var ParentConstructor = function(){
};
var ChildConstructor = function(){
ParentConstructor.call(this)
};
var TempConstructor = function(){};
TempConstructor.prototype = ParentConstructor.prototype;
ChildConstructor.prototype = new TempConstructor();
ChildConstructor.prototype.constructor = ChildConstructor;
You've successfully inherited from the parent class! Let's see if we can do better.
The inherits function
function inherits(childConstructor, parentConstructor){
var TempConstructor = function(){};
TempConstructor.prototype = parentConstructor.prototype; // Inherit parent prototype chain
childConstructor.prototype = new TempConstructor(); // Create buffer object to prevent assignments directly to parent prototype reference.
childConstructor.prototype.constructor = childConstructor; // Reset the constructor property back the the child constructor (currently set to TempConstructor )
};
var ParentConstructor = function(){
};
var ChildConstructor = function(){
ParentConstructor.call(this)
};
inherits(ChildConstructor, ParentConstructor);

Related

JavaScript inherit from two different objects [duplicate]

I'm not very well aquainted with javascript inheritance, and I'm trying to make one object inherit from another, and define its own methods:
function Foo() {}
Foo.prototype = {
getColor: function () {return this.color;},
};
function FooB() {}
FooB.prototype = new Foo();
FooB.prototype = {
/* other methods here */
};
var x = new FooB().getColor();
However, the second one overwrites the first one(FooB.prototype = new Foo() is cancelled out). Is there any way to fix this problem, or am I going in the wrong direction?
Thanks in advance, sorry for any bad terminology.
Each object can only have one prototype, so if you want to add to the prototype after inheriting (copying) it, you have to expand it instead of assigning a new prototype. Example:
function Foo() {}
Foo.prototype = {
x: function(){ alert('x'); },
y: function(){ alert('y'); }
};
function Foo2() {}
Foo2.prototype = new Foo();
Foo2.prototype.z = function() { alert('z'); };
var a = new Foo();
a.x();
a.y();
var b = new Foo2();
b.x();
b.y();
b.z();
One solution would be:
function FooB() {}
var p = new Foo();
p.methodA = function(){...}
p.methodB = function(){...}
p.methodC = function(){...}
...
FooB.prototype = p;
Update: Regarding expanding with an existing object. You can always copy the existing properties of one object to another one:
FooB.prototype = new Foo();
var proto = {
/*...*/
};
for(var prop in proto) {
FooB.prototype[prop] = proto[prop];
}
As long as proto is a "plain" object (i.e. that does not inherit from another object) it is fine. Otherwise you might want to add if(proto.hasOwnProperty(prop)) to only add non-inherited properties.
You can use an extend function which copies the new members to the prototype object.
function FooB() {}
FooB.prototype = new FooA();
extend(FooB.prototype, {
/* other methods here */
});
extend
/**
* Copies members from an object to another object.
* #param {Object} target the object to be copied onto
* #param {Object} source the object to copy from
* #param {Boolean} deep whether the copy is deep or shallow
*/
function extend(target, source, deep) {
for (var i in source) {
if (deep || Object.hasOwnProperty.call(source, i)) {
target[i] = source[i];
}
}
return target;
}

Parameter is not passed from child to parent

I'm trying to pass a parameter from the child module to the parent module constructor but for some reasons the parameter is not passed to the parent.
This is the child module:
var Child = (function()
{
/**
* #constructor
*/
var Child = function(offer)
{
_Parent.call(this, offer);
};
/**
* Prototype.
*/
Child.prototype = Object.create(_Parent.prototype);
Child.prototype.construct = Child;
return Child;
}());
And the following is the parent:
var _Parent = (function()
{
/**
* Contains the offer data.
*
* #type {{}}
*/
var offerData = {};
/**
* #construct
*/
var _Parent = function(offer)
{
offerData = offer;
};
/**
* Get the offer price.
*
* #param offering Index of the offering of which the price should be returned.
*/
var getPrice = function(offering)
{
if(typeof offering == 'undefined')
{
offering = 0;
}
return offerData[offering]['Prices']['PriceRow']['TotalPriceInclVAT'];
};
/**
* Prototype.
*/
_Parent.prototype = {
construct : _Parent,
getPrice : getPrice
};
return _Parent;
}());
I'm trying the getPrice() function on the child like this:
var child = new Child(offers);
child.getPrice();
but I receive always Uncaught TypeError: Cannot read property 'undefined' of undefined inside the getPrice function whenever i try to return the data.
Are you sure offers isn't undefined?
Another problem is that offerData isn't an instance property but a variable inside a closure where the Parent constructor is defined. When you create a new instance, it will override offerData in the closure, wiping out whatever was defined by the previous instantiation.
It's the same as doing this:
var foo = {};
function Parent(bar){
foo = bar;
}
Parent.prototype.getFoo = function(){
return foo;
}
function Child(bar){
Parent.call(this, bar);
}
Child.prototype = Object.create(Parent.prototype);
var hello = new Parent('Hello');
console.log(hello.getFoo()); // Hello
var world = new Child('World');
console.log(world.getFoo()); // World
console.log(hello.getFoo()); // World... wut???
This can be remedied by putting offerData as an instance property so it attaches per instance. You can always resort to pseudo-privates (prefix _ by convention) if you want to keep the concept of privacy.
var _Parent = function(offer){
this._offerData = offer;
};
It is because you defined _Parent only after you defined Child.
You need to first define _Parent and then the Child because the Child uses the parent in the line
Child.prototype = Object.create(_Parent.prototype)
I tested it, and it worked.

JS Inheritance: calling the parent's function from within the child's function

There must be something I don't understand about the JS object model.
From these resources:
Prototypes
Basic OOP in JS- Inheritance
Object.create()
I have gathered what I think, or thought, was an accurate mental representation of the object model. Here it is:
All objects have a property, which the docs refer to as [[Prototype]]. [[Prototype]] can be thought of as a reference to the object's parent. More accurately:
The reference to the [parent's] prototype object is copied to the
internal [[Prototype]] property of the new instance. (source 1)
You can get access to the [[Prototype]] property of the child with Object.getPrototypeOf(child) The value returned here will be a reference to the parent's prototype (not its internal [[Prototype]] property, but its actual prototype)
obj.prototype is different from the object's internal [[Prototype]] property. It acts like the blueprints used to make instances of this exact object, while its [[Prototype]] property points to the blueprints used to make instances of its parent.
Parent.prototype === Object.getPrototypeOf(child); //true
To elaborate:
If you add a function to child.prototype the function will be available to child and any of it's children.
If you add a function to parent.prototype, which is equivalent to adding a function to Object.getPrototypeOf(child), then the function will be available to parent and all of it's children, which includes child and all of its siblings.
You can use Object.create() to create a new object with whatever [[Protoype]] property you want. So you can use it as a way to implement inheritance. See source 2 for an example.
With this in mind, I wanted to get a working example of my own going. My plan was to create a parent 'class' and then make a child 'class' that inherited from it.
I wanted the child class to implement a method, which overloaded a method from the parent. The caveat is that I want the child's version of the method to call the parent's version of the method and then do some extra stuff.
Here is what I came up with, see below for the issues associated with it:
var Parent = function() {};
Parent.prototype.myF = function() {
console.log('derp');
};
function Child() {
Parent.call(this);
};
//make [[prototype]] of Child be a ref to Parent.prototype
Child.prototype = Object.create(Parent.prototype);
//need to explicitly set the constructor
Child.prototype.constructor = Child;
Child.prototype.myF = function() {
Object.getPrototypeOf(this).myF();
console.log("did I derp??");
};
childInstance = new Child();
childInstance.myF();
It appears to be the case that when I attempt to overload Parent.myF(), while I am overloading it, I am actually modifying the original function at the same time. This appears to be the case because the logged results are:
'derp'
'did I derp??'
'did I derp??'
presumably the first occurance of 'did I derp??' is coming from a modified version of the parent's function, which I don't mean to do, then the second version is coming from the child's function.
Can anyone elaborate on why this is happening?
Great question, it took a bit of testing and researching to find it out.
Identifying the strange behaviour
I changed your code a little bit to find out which function is called when:
var Parent = function() {};
Parent.prototype.myF = function() {
console.log('derp');
};
function Child() {
Parent.call(this);
this.name = 'Test'; // this is a new test property
};
//make [[prototype]] of Child be a ref to Parent.prototype
Child.prototype = Object.create(Parent.prototype);
//need to explicitly set the constructor
Child.prototype.constructor = Child;
Child.prototype.myF = function() {
console.log(this); // here I want to find out the context, because you use it in the next line
Object.getPrototypeOf(this).myF();
console.log("did I derp??");
};
childInstance = new Child();
childInstance.myF();
You can check out the JSFiddle and try it for yourself: http://jsfiddle.net/Lpxq78bs/
The crucial line in your code is this:
Child.prototype.myF = function() {
Object.getPrototypeOf(this).myF(); // this one
console.log("did I derp??");
};
After doing a console.log(this); to find out what this refers to, I saw that it changes between the first and the second output of did I derp??.
I got the following output:
Object { name: "Test" }
Object { constructor: Child(), myF: window.onload/Child.prototype.myF() }
"derp"
"did I derp??"
"did I derp??"
Interpreting the Output
Since I added a 'name' property to the Child constructor, it would only be around if I am looking at an instance of Child, not at its .prototype.
So the first line of the Output means that the current this context is indeed the childInstance. But the second one is neither the childInstance, nor the Parent.prototype:
Call (myF of childInstance): this refers to the childInstance. Object.getPrototypeOf(this).myF(); then looks for the [[Prototype]] of the childInstance, which is the Child.prototype, not the Parent.prototype.
Output: 'did I derp??'
Call (myF of Child.prototype): this refers to the Child.prototype, which is the childInstances [[Prototype]] Property. So the second call of Object.getPrototypeOf(this).myF(); finally returns the Parent.prototype (sort of). Output: 'did I derp??'
Call (myF of Parent.prototype instance created by Object.create): Finally, the myF on the parent is called. Output: 'derp'
Since your console.log("did I derp??") comes after the myF function call, the output is in reverse order. The following graphic illustrates how the code is traversed:
So your assumption about what Object.getPrototypeOf(this).myF(); refers to, was wrong.
Solution in ES5
By #LukeP:
https://jsfiddle.net/Lpxq78bs/28/
Alternative Solution in ES6
To avoid this confusion, and since you are working with a classical inheritance pattern, you could have a look at ES6 Classes. The following would be a rough example of what you are trying to do:
class Parent {
constructor() {
}
myF() {
console.log('derp');
}
}
class Child extends Parent {
constructor() {
super();
}
myF() {
super.myF();
console.log("did I derp??");
}
}
var childInstance = new Child();
childInstance.myF();
I hope this helps in understanding what happens.
Your code is working as expected , the output you are getting is because of Object.getPrototypeOf and can be explained by
Step 1 : When you cal childInstance.myF(); then it goes to below code where this refers to childInstance itself
Child.prototype.myF = function() {
Object.getPrototypeOf(this).myF();
console.log("did I derp??");
};
then Object.getPrototypeOf returns childInstance.[[Prototype]] which is Child.prototype and again call myF method(leaving second line to printed later after the execution of the method) but next time this will reference to childInstance.[[Prototype]].
Step 2 : In this call this points to childInstance.[[Prototype]]( or Child.prototype object itself)
Child.prototype.myF = function() {
Object.getPrototypeOf(this).myF();
console.log("did I derp??");
};
Now Object.getPrototypeOf returns childInstance.[[Prototype]].[[Prototype]]( which is Child.prototype.[[Prototype]]) which is Parent.prototype and again call myF method but this time myF method will print derp because myF method of Parent.prototype is being called. After that, second line will print did i derp.
Step 3 : Then the function comes back to step 1 to execute second line which again prints did i derp
If you have to work with inheritance in ES5 I have made a wrapper that makes it easy to extend and call parent methods. No frameworks required.
fiddle to working code here: https://jsfiddle.net/wcrwLmrk/13/
Here is how the code works:
/* extend the base class to the new parent class and pass
an object with the new properties and methods */
var ParentClass = Class.extend(
{
// reset the constructor to the correct constructor
constructor: function()
{
},
callName: function(arg)
{
console.log('parent ' + arg);
}
});
/* extend the parent class to the new child class and pass
an object with the new properties and methods */
var ChildClass = ParentClass.extend(
{
// reset the constructor to the correct constructor
constructor: function()
{
ParentClass.call(this);
},
callName: function(arg)
{
// child method code
console.log('child ' + arg);
/* call parent method by passing the method name and any params */
this.super('callName', arg);
}
});
Now we can create a new child class that will
call the super class method:
var child = new ChildClass();
child.callName('name');
Here is the base class that needs to be included in the project:
var Class = function()
{
};
Class.prototype =
{
constructor: Class,
/* this is an alias for callParent. this will
allow child classes to call super methods.
#param (string) method name
#param [(mixed)] addasmany args as the super
method needs
#return (mixed) the super method return value */
super: function()
{
var parent = this.parent;
if(parent)
{
var args = [].slice.call(arguments),
// this will remove the first arg as the method
method = args.shift();
if(method)
{
var func = parent[method];
if(typeof func === 'function')
{
return func.apply(this, args);
}
}
}
return false;
}
};
/* this will return a new object and extend it if an object it supplied.
#param [(object)] object = the extending object
#return (object) this will return a new object with the
inherited object */
var createObject = function(object)
{
if(!Object.create)
{
var obj = function(){};
obj.prototype = object;
return new obj();
}
else
{
return Object.create(object);
}
};
/* this will extend an object and return the extedned
object or false.
#param (object) sourceObj = the original object
#param (object) targetObj = the target object */
var extendObject = function(sourceObj, targetObj)
{
if(typeof sourceObj !== 'undefined' && typeof targetObj !== 'undefined')
{
for(var property in sourceObj)
{
if(sourceObj.hasOwnProperty(property) && typeof targetObj[property] === 'undefined')
{
targetObj[property] = sourceObj[property];
}
}
return targetObj;
}
return false;
};
var extendClass = function(sourceClass, targetClass)
{
/* if we are using a class constructor function
we want to get the class prototype object */
var source = (typeof sourceClass === 'function')? sourceClass.prototype : sourceClass,
target = (typeof targetClass === 'function')? targetClass.prototype : targetClass;
if(typeof source === 'object' && typeof target === 'object')
{
/* we want to create a new object and add the source
prototype to the new object */
var obj = createObject(source);
/* we need to add any settings from the source that
are not on the prototype */
extendObject(source, obj);
/* we want to add any additional properties from the
target class to the new object */
for(var prop in target)
{
obj[prop] = target[prop];
}
return obj;
}
return false;
};
/* this will allow the classes to be extened.
#param (object) child = the child object to extend
#return (mixed) the new child prototype or false */
Class.extend = function(child)
{
if(!child)
{
return false;
}
var parent = this.prototype;
/* the child constructor must be set to set
the parent static methods on the child */
var constructor = child && child.constructor? child.constructor : false;
if(child.hasOwnProperty('constructor') === false)
{
constructor = function()
{
var args = arguments;
parent.constructor.apply(this, args);
};
}
constructor.prototype = extendClass(parent, child);
constructor.prototype.parent = parent;
/* this will add the static methods from the parent to
the child constructor. */
extendObject(this, constructor);
return constructor;
};

javascript inheritance, constructor called twice

function Parent (arg1, arg2) {
alert(arg1);
this.member1 = arg1;
this.member2 = arg2;
};
Parent.prototype.update = function () {
// parent method update
};
function Child (arg1, arg2, arg3) {
Parent.call(this, arg1, arg2);
this.member3 = arg3;
};
Child.prototype = new Parent;
Child.prototype.update = function () {
// overwritten method update
};
function init () {
var childObject = new Child(false, false, false);
childObject.update();
}
The result are two alerts with
undefined
false
Why does the alert occurs two times? I already searched, but haven't found anything yet + don't know what to search for.
The result should be one alert with 'false', or am i wrong?
Thx alot!
By using the constructor of Parent to create the prototype for Child, the constructor is being called which is your first alert of undefined.
In order to create a prototype that still uses the same prototype chain, but doesn't call the parent constructor as the prototype is created, you need to add another step in between.
Child.prototype = (function() {
var Base = function() {};
Base.prototype = Parent.prototype;
return new Base();
}());
This will create an anonymous function (called Base) that has the prototype set to be the prototype of the Parent class, the Child prototype is then assigned to a new Base which will preserve the inheritance, but doesn't call the constructor of Parent as the prototype chain is created.
There is one alert when you create a new object of Parent Child.prototype = new Parent; and one when you create new object of child, var childObject = new Child(false, false, false);

Why is `goog.base(this)` necessary in addition to `goog.inherits()`?

In this snippet of Google Closure javascript code involving a constructor, why is goog.base(this); necessary? Doesn't Foo already inherit from Disposable with goog.inherits(foo, goog.Disposable);?
goog.provide('Foo');
/**
* #constructor
* #extends {goog.Disposable}
*/
Foo = function() {
goog.base(this);
}
goog.inherits(foo, goog.Disposable);
foo.prototype.doSomething = function(){
...
}
foo.prototype.disposeInternal = function(){
...
}
goog.inherits(childConstructor, parentConstructor)
goog.inherits() establishes the prototype chain from the child constructor
to the parent constructor.
/**
* Inherit the prototype methods from one constructor into another.
* #param {Function} childCtor Child class.
* #param {Function} parentCtor Parent class.
*/
goog.inherits = function(childCtor, parentCtor) {
/** #constructor */
function tempCtor() {};
tempCtor.prototype = parentCtor.prototype;
childCtor.superClass_ = parentCtor.prototype;
childCtor.prototype = new tempCtor();
/** #override */
childCtor.prototype.constructor = childCtor;
};
In addition to prototype properties, constructors may have "own" properties
(i.e. instance-specific properties added to this). Since goog.inherits()
does not call the parent constructor, own properties are not copied to the
child constructor and any initialization code in the parent does not get
executed. For these reasons, the standard pattern is to chain constructors as in the following example.
/**
* #param {string} name The parent's name.
* #constructor
*/
var Parent = function(name) {
/**
* #type {string}
* #private
*/
this.name_ = name;
}
/**
* #param {string} name The child's name.
* #constructor
* #extends {Parent}
*/
var Child = function(name) {
Parent.call(this, name);
}
goog.inherits(Child, Parent);
goog.base(self, opt_methodName, var_args)
goog.base() is a helper function for calling parent methods so that you do
not need to explicitly use call() or apply().
If [goog.base()] is called from a constructor, then this calls the
superclass contructor with arguments 1-N.
If this is called from a prototype method, then you must pass the name of
the method as the second argument to this function. If you do not,
you will get a runtime error. This calls the superclass' method with
arguments 2-N.
This function only works if you use goog.inherits to express inheritance
relationships between your classes.
In Closure code it is common to chain constructors with goog.base() rather
than calling the parent constructor explicitly.
/**
* #param {string} name The child's name.
* #constructor
* #extends {Parent}
*/
var Child = function(name) {
goog.base(this, name);
}
goog.inherits(Child, Parent);
Further Reading
Inheritance Patterns in JavaScript by Michael Bolin
An Examination of goog.base() by Michael Bolin
Closure: The Definitive Guide by Michael Bolin
JavaScript Patterns by Stoyan Stefanov (see Chapter 6: "Code Reuse Patterns" for a detailed analysis of the pattern used to implement goog.inherits() - Classical Pattern #5--A Temporary Constructor)
In JavaScript, this is set entirely by how the function is called, not where it's defined (as it is in Java, C#, and C++). So to make this within the call to goog.Disposable be the this of where you're calling it, you have to use .call or .apply. Otherwise, if you just called goog.Disposable(), within the call this would be goog.
Basically, there are two ways to set this for the function you're calling:
Use obj.func() or obj["func"]() notation — e.g., make the call as part of the same overall expression where you're retrieving a property from the object. This tells the engine that within the call, you want this to refer to obj.
Use call or apply to be more explicit about it by supplying the object to use as this as the first argument. The only difference between call and apply is how you supply other arguments: With call, you supply them as discrete args, e.g. foo.call(obj, 1, 2, 3) calls foo with this set to obj and the arguments 1, 2, and 3. With apply, you supply the arguments as an array-like second argument: foo.apply(obj, [1, 2, 3]); (note the [ and ]; e.g. var a = [1, 2, 3]; foo.call(obj, a);
More to explore:
Mythical methods
You must remember this
You can see
Foo = function() {
goog.base(this); //call parent constructor
}
goog.inherits(foo, goog.Disposable);
As:
public class Foo extends Disposable(){
public Foo(){
super(); // call parent constructor
}
}

Categories