63779

JavaScript build a constructor of constructors

Question:

Here is a simple example of what I want :

var ConstBuilder = function() { var constructor = function() {} ; constructor.prototype = {} ; return constructor ; } ; ConstBuilder.prototype = { add : function(name, value) { this.prototype[name] = value ; } } ; var A = new ConstBuilder() ; A.add('test', function() { console.log('test') ; }) ; var a = new A() ; a.test() ;

This code will fail as A is not an instance of ConstBuilder (because A comes from a returned var constructor = function() {} and won't have the methods defined in its prototype (add).

But this would be useful to modify the super constructor's prototype to have things like :

ConstBuilder.prototype.remove = function(name) { delete this.prototype[name] ; } ; A.remove('test') ; a.test ; // undefined

Is there a way to have a function as an instance of another ? So this function may implicitely "inherit" all the methods defined in its constructor's prototype.

Or if you have other suggestions, I aim to build modulable constructors - as instances with prototypes are.

Answer1:

Please make sure you have understood the difference between the .prototype property and the internal inheritance-prototype.

<hr /><blockquote>

The code will fail as A is not an instance of ConstBuilder. Is there a way to have a function as an instance of another?

</blockquote>

A is, as every constructor needs to be, a <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function" rel="nofollow">Function</a>. So if you just define your add and remove methods on the Function.prototype, it will work:

Function.prototype.add = function(name, value) { this.prototype[name] = value; }; Function.prototype.remove = function(name) { delete this.prototype[name]; }; function A() {} A.add('test', function(){console.log('test');}); var a = new A(); a.test(); // test A.remove('test'); a.test; // undefined

There is no possibility however to let a function inherit from something else than Function.prototype - see <a href="https://stackoverflow.com/questions/340383/can-a-javascript-object-have-a-prototype-chain-but-also-be-a-function" rel="nofollow">Can a JavaScript object have a prototype chain, but also be a function?</a>. If you don't want to modify the native Function.prototype object, you still can use the <a href="http://addyosmani.com/resources/essentialjsdesignpatterns/book/#mixinpatternjavascript" rel="nofollow">mixin pattern</a>:

var Constr = (function() { function add(name, value) { this.prototype[name] = value; } function remove(name) { delete this.prototype[name]; } return function mixin(c) { c.add = add; c.remove = remove; return c; }; })(); var A = Constr(function() {…}); A.add("test", …); var a = new A(); a.test(); // test <blockquote>

I aim to build modulable constructors

</blockquote>

You could use the <a href="https://en.wikipedia.org/wiki/Builder_pattern" rel="nofollow">builder pattern</a>, as you just have seem to tried.

function ConstBuilder() { this.prototype = {}; }; ConstBuilder.prototype = { add: function(name, value) { this.prototype[name] = value; }, remove: function(name) { delete this.prototype[name]; }, getConstructor: function() { var constructor = function() {}; constructor.prototype = this.prototype; this.prototype.constructor = constructor; return constructor; } }; var A = new ConstBuilder().add('test', function() { console.log('test'); }).getConstructor(); var a = new A(); a.test(); // test

To remove functions later, you would need to save a reference to the builder.

Answer2:

I think that you are looking for an example of how to do JavaScript's "prototypical inheritance". When JavaScript looks for a property on an object, it first checks the object itself. Next it checks the prototype. However, since everything in JavaScript is an object and the prototype is an object

function Root(){} Root.prototype.fromRoot = function() { console.log("I'm on Root's prototype."); }; function Child(){} Child.prototype = new Root(); Child.prototype.fromChild = function() { console.log("I'm on Child's prototype."); }; var r = new Root(); var c = new Child(); r.fromRoot(); // works c.fromRoot(); // works c.fromChild(); // works r.fromChild(); // fails

Answer3:

function a (x,y,construct) { if (!construct) return; this.x=x; this.y=y; } a.prototype.methoda=function () { return x+y; } function b (x,y,d,e) { a.call (this,x,y,true) //--- this would inherit all own Objects and Properties of a and become own properties of b this.d=d; this.e=e; } b.prototype=new a (); //--- this would only inherit the prototype, construct becomes false and isnt worked through, which if not would result in adding propertiy x and y to prototype instead of directly to instance of b, b.prototype.constructor=b; var test=new b (1,2,3,4); b.methoda ();

second way

function a (x,y) { if (arguments.callee.doNotConstruct) return; this.x=x; this.y=y; } a.prototype.methoda=function () { return x+y; } function b (x,y,d,e) { a.call (this,x,y) //--- this would inherit all own Objects and Properties of a and become own properties of b this.d=d; this.e=e; } a.doNotConstruct=true; b.prototype=new a (); //--- this would only inherit the prototype, construct becomes false and isnt worked through, which if not would result in adding propertiy x and y to prototype instead of directly to instance of b, a.doNotConstruct=false; b.prototype.constructor=b; var test=new b (1,2,3,4); b.methoda ();

put this in a function

function prototypeInheritance (inheritor,parent) { parent.doNotConstruct=true; inheritor=new parent (); inheritor.prototype.constructor=inheritor; inheritor.parent=parent; parent.doNotConstruct=false; }

you can call the parent property with (arguments.callee.parent) in the inheritor constructor and you can check doNotConstruct with arguments.callee.doNotConstruct in the parent constructor

Recommend

  • Confused about Douglas Crockford's object function
  • C++ numerical integrators to solve systems of ode's
  • Two .lib containing different functions with the same name: how to choose the right one?
  • Is it possible to install cupy on google colab?
  • add a custom base class for web forms
  • Possible to avoid default call to super() in Java?
  • Chrome only: Overlay divs on scroll with fixed position scrolling issue
  • Is it possible to manage the top navigation bar using SharePoint web services?
  • Problem in Z-index of menu and ajax ModalPopupExtender in ASP.net
  • How do I catch c0000005 exception from native dll in c#
  • How to get UIBarButtonItem center position
  • Is there an jQuery equivalent of MooTools Hash?
  • Callback, specified in QueueUserAPC , does not get called
  • Vectors and abstract classes
  • Confusion with the order of execution when `next` with `unless` in ruby
  • Segmentation fault when accessing a list inside a struct
  • Excel - Formula or Macro to fill a cell based on another cell that links to yet another cell
  • Call json.Unmarshal inside UnmarshalJSON function without causing stack overflow
  • SQLite HAVING comparison error
  • declaring device constant in terms of another constant
  • Can a structure tag be used before its scope?
  • Setting inner div opacity to 1, but not effected
  • Embedded h2 database: getting connection but table not found
  • Dropdown menu with the dropdown-menu-right class does not align to the right
  • Looking for datastructure that maintains a size & purges older elements in the process
  • Why is new Number(8) not exactly equal to 8?
  • a concept similar to pointers in as3?
  • Ant: fileset “dir” attribute with a runtime expanded full path
  • Fixed Background Works in Chrome but Not Firefox?
  • LNK1104: cannot open file 'kernel32.lib'
  • Validation fired but Red Border does not appear with User Control in Silverlight 4
  • custom string delimiters stringtemplate-4
  • Invert string in Rust
  • Less Conflicting Session Manager for Zope 2
  • Jquery Knockout: ko.computed() vs classic function?
  • Java color detection
  • calculate gradient output for Theta update rule
  • zope_i18n_compile_mo_files doesn't work on a Zeo configuration
  • OOP Javascript - Is “get property” method necessary?
  • Scrapy recursive link crawler