Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Not so fast. It just doesn't work.</p> <p>Consider:</p> <pre><code>var p = new Person(true); alert("p.dance()? " + p.dance()); =&gt; true var n = new Ninja(); alert("n.dance()? " + n.dance()); =&gt; false n.dancing = true; alert("n.dance()? " + n.dance()); =&gt; false </code></pre> <p><code>base</code> is just another object initialized with default members that made you think it works.</p> <p>EDIT: for the record, here is my own (albeit more verbose) implementation of Java like inheritance in Javascript, crafted in 2006 at the time I got inspired by <a href="http://dean.edwards.name/weblog/2006/03/base/" rel="nofollow noreferrer">Dean Edward's Base.js</a> (and I agree with him when <a href="http://ejohn.org/blog/simple-javascript-inheritance/#comment-299623" rel="nofollow noreferrer">he says John's version is just a rewrite of his Base.js</a>). <a href="http://gregory.pakosz.fr/stackoverflow/2510342.html" rel="nofollow noreferrer">You can see it in action (and step debug it in Firebug) here</a>.</p> <pre><code>/** * A function that does nothing: to be used when resetting callback handlers. * @final */ EMPTY_FUNCTION = function() { // does nothing. } var Class = { /** * Defines a new class from the specified instance prototype and class * prototype. * * @param {Object} instancePrototype the object literal used to define the * member variables and member functions of the instances of the class * being defined. * @param {Object} classPrototype the object literal used to define the * static member variables and member functions of the class being * defined. * * @return {Function} the newly defined class. */ define: function(instancePrototype, classPrototype) { /* This is the constructor function for the class being defined */ var base = function() { if (!this.__prototype_chaining &amp;&amp; base.prototype.initialize instanceof Function) base.prototype.initialize.apply(this, arguments); } base.prototype = instancePrototype || {}; if (!base.prototype.initialize) base.prototype.initialize = EMPTY_FUNCTION; for (var property in classPrototype) { if (property == 'initialize') continue; base[property] = classPrototype[property]; } if (classPrototype &amp;&amp; (classPrototype.initialize instanceof Function)) classPrototype.initialize.apply(base); function augment(method, derivedPrototype, basePrototype) { if ( (method == 'initialize') &amp;&amp;(basePrototype[method].length == 0)) { return function() { basePrototype[method].apply(this); derivedPrototype[method].apply(this, arguments); } } return function() { this.base = function() { return basePrototype[method].apply(this, arguments); }; return derivedPrototype[method].apply(this, arguments); delete this.base; } } /** * Provides the definition of a new class that extends the specified * &lt;code&gt;parent&lt;/code&gt; class. * * @param {Function} parent the class to be extended. * @param {Object} instancePrototype the object literal used to define * the member variables and member functions of the instances of the * class being defined. * @param {Object} classPrototype the object literal used to define the * static member variables and member functions of the class being * defined. * * @return {Function} the newly defined class. */ function extend(parent, instancePrototype, classPrototype) { var derived = function() { if (!this.__prototype_chaining &amp;&amp; derived.prototype.initialize instanceof Function) derived.prototype.initialize.apply(this, arguments); } parent.prototype.__prototype_chaining = true; derived.prototype = new parent(); delete parent.prototype.__prototype_chaining; for (var property in instancePrototype) { if ( (instancePrototype[property] instanceof Function) &amp;&amp;(parent.prototype[property] instanceof Function)) { derived.prototype[property] = augment(property, instancePrototype, parent.prototype); } else derived.prototype[property] = instancePrototype[property]; } derived.extend = function(instancePrototype, classPrototype) { return extend(derived, instancePrototype, classPrototype); } for (var property in classPrototype) { if (property == 'initialize') continue; derived[property] = classPrototype[property]; } if (classPrototype &amp;&amp; (classPrototype.initialize instanceof Function)) classPrototype.initialize.apply(derived); return derived; } base.extend = function(instancePrototype, classPrototype) { return extend(base, instancePrototype, classPrototype); } return base; } } </code></pre> <p>And this is how you use it:</p> <pre><code>var Base = Class.define( { initialize: function(value) // Java constructor equivalent { this.property = value; }, property: undefined, // member variable getProperty: function() // member variable accessor { return this.property; }, foo: function() { alert('inside Base.foo'); // do something }, bar: function() { alert('inside Base.bar'); // do something else } }, { initialize: function() // Java static initializer equivalent { this.property = 'Base'; }, property: undefined, // static member variables can have the same // name as non static member variables getProperty: function() // static member functions can have the same { // name as non static member functions return this.property; } }); var Derived = Base.extend( { initialize: function() { this.base('derived'); // chain with parent class's constructor }, property: undefined, getProperty: function() { return this.property; }, foo: function() // override foo { alert('inside Derived.foo'); this.base(); // call parent class implementation of foo // do some more treatments } }, { initialize: function() { this.property = 'Derived'; }, property: undefined, getProperty: function() { return this.property; } }); var b = new Base('base'); alert('b instanceof Base returned: ' + (b instanceof Base)); alert('b.getProperty() returned: ' + b.getProperty()); alert('Base.getProperty() returned: ' + Base.getProperty()); b.foo(); b.bar(); var d = new Derived('derived'); alert('d instanceof Base returned: ' + (d instanceof Base)); alert('d instanceof Derived returned: ' + (d instanceof Derived)); alert('d.getProperty() returned: ' + d.getProperty()); alert('Derived.getProperty() returned: ' + Derived.getProperty()); d.foo(); d.bar(); </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload