Required template: create a new object that returns an executable function and inherits from the prototype

Scenario 1 - everything works:

var AwesomeObject = function() { var self = this; self.whatstuff = 'really awesome'; } AwesomeObject.prototype.doStuff = function() { var self = this; console.log('i did '+self.whatstuff+' stuff'); return self; } var awesome = new AwesomeObject(); //returns a new AwesomeObject awesome.doStuff(); // prints 'i did really awesome stuff' on the console 

Now I want it to be even awesomer:

 var AwesomeObject = function() { var f = function() { console.log('i am awesome'); } var self = f; self.whatstuff = 'really awesome'; return self; } AwesomeObject.prototype.doStuff = function() { var self = this; console.log('i did '+self.whatstuff+' stuff'); return self; } var awesome = new AwesomeObject(); //returns the interal f object awesome(); // prints 'i am awesome' awesome.doStuff(); // throws an error 

new AwesomeObject should return an executable function, so I can say "awesome ();

but I want it to inherit AwesomeObject.prototype .

adding self.prototype = AwesomeObject.prototype; Does not help.

 var AwesomeObject = function() { var f = function() { console.log('i am awesome'); } var self = f; self.whatstuff = 'really awesome'; self.prototype = AwesomeObject.prototype; return self; } 

ok I can copy the functions of AwesomeObject.prototype - one by one - to the area f

 var AwesomeObject = function() { var f = function() { console.log('i am awesome'); } var self = f; self.whatstuff = 'really awesome'; self.doStuff = function() { AwesomeObject.prototype.doStuff.apply(self,arguments); } return self; } 

but I think that there should be a better way, a better sample, what is it?

this problem is driving me crazy, help will be really appreciated.

in general: how to create a function object that

  • can be created using the new
  • returns a function object that can be executed
  • inherits all the properties and methods of this prototype

?

is there any way?

THX Franz

+6
source share
3 answers

A very simple template is a factory.

 var AwesomeObject = (function() { var AwesomeObject = function() { this.whatstuff = 'really awesome'; }; AwesomeObject.prototype.doStuff = function() { console.log('i did ' + this.whatstuff + ' stuff'); return this; }; return function() { var o = new AwesomeObject(); var f = function() { console.log("I am awesome"); }; for (var k in o) { f[k] = o[k]; } return f; }; })(); var foo = AwesomeObject(); foo(); foo.doStuff(); 

Living example .

The idea is that you separate your function and your object into two things. Your object exists in the local area of ​​your function, and the function can use the object.

The object itself is fully inherited through the prototype.

The key sends all the properties / methods of the object to the function.

This is the cleanest solution.

+8
source

When a property is enabled, the prototype chain goes through, as you probably know. But if you have an awesome object and try to evaluate awesome.doStuff , then awesome.prototype will never be requested for the property. You can check this in your example, "doStuff" in awesome => false , but "doStuff" in awesome.prototype => true .

So what you are doing is not changing the implicit properties of awesome , you are changing its prototype, that is, any objects created when new awesome executed will have this property. Check: "doStuff" in new awesome() => true . And that makes sense, since using f/awesome it is not possible to distinguish between a constructor or a regular function.

The procedure for resolving the property p object o looks like this:

  • Check if p defined on o
  • Check if p exists on o.__proto__ (using __proto__ is non-standard but widely implemented, except that jscript is last checked and now it's deprecated in SpiderMonkey)
  • Check if p defined on o.constructor.prototype
  • Check if p exists on o.constructor.prototype.prototype
  • etc.

So one solution would be to simply set o.__proto__ = AwesomeClass.prototype . Think of __proto__ as a hidden intermediate object between the object and its prototype. Each instance gets its own unique __proto__ object. But this is outdated and non-standard, as I said.

We could also set the values ​​in Function.prototype , but this could override other Function properties and affect all instances of Function. We do not want this.

So what's left? Not so much. It is not possible to establish a complete prototype of an object while retaining its inherited prototype. You will need to iterate over the prototype and copy all the properties. Fortunately, this will allow instanceof to behave as expected when working with the goals of the constructors, as well as properly inherit / override properties.

The problem is that there is no built-in way to copy the properties of an object to another and there is no standard way to change the prototype chain of an ad-hoc object ( __proto__ ).

So use __proto__ , or iterate through a prototype.

+2
source

I do not think there is a good way to do this. I would review your program to avoid it.

However, there is a bad solution for the platform (it works on V8 using the non-standard __proto__ property):

 var PrototypeToBeInherited = {'inheritedProperty': 'inheritedPropertyValue'}; f = function() { return "result"; }; f.__proto__ = PrototypeToBeInherited; f() => "result"; f.inheritedProperty => "inheritedPropertyValue" 

For your requirement that it be created using the "new", just wrap it in a function:

 F = function() { return f; } var instance = new F(); 
+1
source

Source: https://habr.com/ru/post/887346/


All Articles