问题
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(){
...
}
回答1:
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)
回答2:
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()
orobj["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 wantthis
to refer toobj
.Use
call
orapply
to be more explicit about it by supplying the object to use asthis
as the first argument. The only difference betweencall
andapply
is how you supply other arguments: Withcall
, you supply them as discrete args, e.g.foo.call(obj, 1, 2, 3)
callsfoo
withthis
set toobj
and the arguments1
,2
, and3
. Withapply
, 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
回答3:
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
}
}
来源:https://stackoverflow.com/questions/11122608/why-is-goog-basethis-necessary-in-addition-to-goog-inherits