How to wrap plain function into a constructor? - javascript

Is it possible to make a wrapper function MyFunction, which when called with new as in
instance = new MyFunction();
really returns the same object as if the callsite called SomeOtherFunction without new?
instance = SomeOtherFunction();
(I've looked at Proxy but doesn't look like they're supported in Chrome yet.)
Edit:
It turns out the callsite calls MyFunction like this:
var instance = Object.create(MyFunction.prototype);
MyFunction.apply(instance, [/* arguments */]);
// `instance` is supposed to be initialized here

I think this is what you are looking for? Note as Jan Dvorak mentioned, you can only return objects.
function SomeObject() {
return Construct();
}
function Construct() {
return { 'name' : 'yessirrreee' };
}
console.log(new SomeObject())

You can try something like this
function MyClass() {
}
var ob = new MyClass();

Edit after comments
I think this questions needs more context.
I suggest you read about higher order components, but until you've better clarified what exactly you're trying to accomplish, I cannot help you.
I really don't know what your code looks like, but here are some suggestions
either way. My guess nr2 is what you're looking for:
// 1
function MyFunction() {
this.__proto__ = SomeOtherFunction()
}
function SomeOtherFunction() {
return {
foo: function() {
return 'bar'
}
}
}
var fn = new MyFunction()
fn.foo()
// 2
function MyFunction() {}
MyFunction.prototype = SomeOtherFunction()
function SomeOtherFunction() {
return {
foo: function() {
return 'bar'
}
}
}
var fn = new MyFunction()
fn.foo()
// 3
function MyFunction() {}
MyFunction.prototype = SomeOtherFunction.prototype
function SomeOtherFunction() {
function Foo() {}
Foo.prototype.foo = function() {
return 'bar'
}
}
var fn = new MyFunction()
fn.foo()

Related

JS closure to return object instance as interface

I have the following code.
function Test() {
this.funct_1 = function() {
alert('funct_1');
}
this.funct_2 = function() {
alert('funct_2');
}
return this;}
function getTestObj() {
var testObj;
if (!testObj) {
testObj = new Test();
}
return function() {
return testObj;
}}
What I'm trying to accomplish is the following. I want to have a class Test which is not singleton. Then in some other places in my application I need to have a function which could return the same instance per script execution. I figured that I could use closure for that getTestObj.
However, when I try to use it
getTestObj().funct_1();
I'm getting the following error, saying the funct_1() is not found.
Cannot find function funct_1 in object function () {...}.
Clearly, I'm making some kind of mistake here, but I'm not able to find any solution over the net which could help me. Would appreciate any comments.
NOTE: I'm forced to use ECMA5
testObj is wrapped inside a function
So, either call it
getTestObj()().funct_1(); //notice two ()()
Save the value of getTestObj() in a variable
var singleTon = getTestObj();
var testObj = singleTon();
testObj.funct_1();
Or, simply return testObj (in case singleTon isn't required)
function getTestObj()
{
var testObj;
if (!testObj) {
testObj = new Test();
}
return testObj;
}
And invoke it as
getTestObj().funct_1(); //notice single ()
getTestObj() is returning a function i.e. :
function() {
return testObj;
}
So you have to call it again getTestObj()(), this will return the Test's object and now you can access it's properties.
getTestObj()().funct_1();
OR
You can change your getTestObj function as :
function getTestObj() {
var testObj;
if (!testObj) {
testObj = new Test();
}
return (function() {
return testObj;
}());
}

Calling an object's prototype method from another object's method

I am trying to create a simple callback system that would fire upon hitting a button. Rather than the callback being a factory function, it is a prototype method of a different object. I've gotten it to work but I don't understand it. Why do I need to use .bind(object) to get the object to fire its method? Originally I tried no bind, and then bind(this), which both failed.
function Bar() {}
Bar.prototype = {
getStuff: function () {
return "Hello";
},
setStuff: function () {
console.log( this.getStuff() );
}
}
function Foo() {
this.afterSubmit = null;
var self = this;
$('button').click(function () {
self.submit()
});
return this;
}
Foo.prototype = {
submit: function () {
if (this.afterSubmit !== null) {
this.afterSubmit();
}
$('#msg').append('clicked ');
return this;
},
setAfterSubmit: function (callback) {
this.afterSubmit = callback;
return this;
}
}
var bar = new Bar();
var foo = new Foo().setAfterSubmit(bar.setStuff.bind(bar));
// Why do I need to bind bar ?
Please take a look at my fiddle
https://jsfiddle.net/j5qfuzna/
this.afterSubmit();
This is setting the context to the Foo instance. Binding it to the Bar instance prevents that from happening.

Parameter of a function within a function

How must a function be 'chained', in order to call this function like this
F('Test').custom_substring(0,1);
You have to return an object that has a method member named custom_substring. One example:
var F = function(){
return {
custom_substring:function(){
console.log('custom substring');
return this;
}
}
}
F('Test')
.custom_substring(0,1)
.custom_substring(0,1)
.custom_substring(0,1);
To create objects you can use constructor functions and prototype, this is a complex subject and explained here.
I would not mess with the String.prototype because that breaks encapsulation.
The following sample provides a chainable custom_substring that does not modify the original object but instead returns a new one. This is similar to how jQuery and other libraries work (and how built-in string operations work) and it helps make for safer and more predictable code.
function F(str) {
return {
toString: function () { return str; },
// You didn't provide an example of what you want custom_substring
// to do, so I'll have it append a "!" to the beginning of the resulting value
// (since I can't think of anything else for it to do)
custom_substring: function (from, to) {
return F("!" + str.substring(from, to));
}
};
}
var s1 = F("Hello everyone");
var s2 = s1.custom_substring(0, 7);
var s3 = s2.custom_substring(0, 5)
.custom_substring(0, 4);
console.log(s1); // Hello everyone
console.log(s2); // !Hello e
console.log(s3); // !!!He
If you really want to create chainloading you need always return this from methods where it's possible.
For example we have some class with some methods:
function Foo() {
this.foo = 'bar';
return this;
}
Foo.prototype = Object.create({
sayFoo: function() {
console.log(this.foo);
return this;
},
getFoo: function() {
return this.foo; // Here you can't make chainload
},
saySmth: function() {
console.log('Something');
return this;
}
});
And we can use this:
var test = new Foo().sayFoo().saySmth().getFoo(); // prints this.foo -> 'Something' -> returns this.foo
console.log(test); // prints out this.foo

How to call one method from another inside function

I have tried to create javascript object like
function Caller() {
this.init = function() {
makeCall();
};
this.makeCall = function(){/*come code here*/}
}
var a = new Caller();
a.init();
I got error function is not defined, same thing happens when I try to call this.makeCall();
When I remove this from makeCall definition it works, but when I remove also from init it doesn't work. How to solve this ?
Use this.makeCall(). Additionally define makeCall() before its use.
function Caller() {
this.makeCall = function () { /*come code here*/ }
this.init = function () {
this.makeCall();
};
}
var a = new Caller();
a.init();
DEMO
Use this.makeCall() it is a method so you can use it.
Try this this.makeCall() function is executed successfully here.
<html>
<head>
</head>
<body>
<script>
function Caller() {
this.init = function() {
this.makeCall();
};
this.makeCall = function(){
alert('hello');
}
}
var a = new Caller();
a.init();
</script>
</body>
</html>
You need to call the function properly using this
makeCall(); => this.makeCall();
You can use IIFE to declare Caller:
var Caller=(function () {
function constructor() {
}
function makeCall() {
/*come code here*/
}
constructor.prototype.init=function () {
makeCall.apply(this, arguments);
};
return constructor;
})();
var a=new Caller();
a.init();
and be sure that Caller is loaded before it is invoked.
To answer your question and to enhance your code you should have a look at this:
function Caller(){};
This is your constructor.
You can then add methods to your constructor like this:
Caller.prototype.init = function () {
// do something
}
When you create instances of your "class" Caller
var a = new Caller();
every instance will have the methods you described in the Caller.prototype object.
And to solve your problem:
If one prototype method wants to call another prototype method, you need to do this:
// do some setup in your constructor
function Caller(phoneNumber) {
this.phoneNumber = phoneNumber;
};
Caller.prototype.init = function () {
// the code word "this" will be the instance itself
this.makeCall();
};
Caller.prototype.makeCall = function () {
// do whatever this method needs to do
alert('calling ' + this.phoneNumber);
};
var a = new Caller(0123456789);
a.init();
The main thing to understand is, that in every prototype method, the keyword this references the current instance of the constructor (in this case Caller).

Calling method using JavaScript prototype

Is it possible to call the base method from a prototype method in JavaScript if it's been overridden?
MyClass = function(name){
this.name = name;
this.do = function() {
//do somthing
}
};
MyClass.prototype.do = function() {
if (this.name === 'something') {
//do something new
} else {
//CALL BASE METHOD
}
};
I did not understand what exactly you're trying to do, but normally implementing object-specific behaviour is done along these lines:
function MyClass(name) {
this.name = name;
}
MyClass.prototype.doStuff = function() {
// generic behaviour
}
var myObj = new MyClass('foo');
var myObjSpecial = new MyClass('bar');
myObjSpecial.doStuff = function() {
// do specialised stuff
// how to call the generic implementation:
MyClass.prototype.doStuff.call(this /*, args...*/);
}
Well one way to do it would be saving the base method and then calling it from the overriden method, like so
MyClass.prototype._do_base = MyClass.prototype.do;
MyClass.prototype.do = function(){
if (this.name === 'something'){
//do something new
}else{
return this._do_base();
}
};
I'm afraid your example does not work the way you think. This part:
this.do = function(){ /*do something*/ };
overwrites the definition of
MyClass.prototype.do = function(){ /*do something else*/ };
Since the newly created object already has a "do" property, it does not look up the prototypal chain.
The classical form of inheritance in Javascript is awkard, and hard to grasp. I would suggest using Douglas Crockfords simple inheritance pattern instead. Like this:
function my_class(name) {
return {
name: name,
do: function () { /* do something */ }
};
}
function my_child(name) {
var me = my_class(name);
var base_do = me.do;
me.do = function () {
if (this.name === 'something'){
//do something new
} else {
base_do.call(me);
}
}
return me;
}
var o = my_child("something");
o.do(); // does something new
var u = my_child("something else");
u.do(); // uses base function
In my opinion a much clearer way of handling objects, constructors and inheritance in javascript. You can read more in Crockfords Javascript: The good parts.
I know this post is from 4 years ago, but because of my C# background I was looking for a way to call the base class without having to specify the class name but rather obtain it by a property on the subclass. So my only change to Christoph's answer would be
From this:
MyClass.prototype.doStuff.call(this /*, args...*/);
To this:
this.constructor.prototype.doStuff.call(this /*, args...*/);
if you define a function like this (using OOP)
function Person(){};
Person.prototype.say = function(message){
console.log(message);
}
there is two ways to call a prototype function: 1) make an instance and call the object function:
var person = new Person();
person.say('hello!');
and the other way is... 2) is calling the function directly from the prototype:
Person.prototype.say('hello there!');
This solution uses Object.getPrototypeOf
TestA is super that has getName
TestB is a child that overrides getName but, also has
getBothNames that calls the super version of getName as well as the child version
function TestA() {
this.count = 1;
}
TestA.prototype.constructor = TestA;
TestA.prototype.getName = function ta_gn() {
this.count = 2;
return ' TestA.prototype.getName is called **';
};
function TestB() {
this.idx = 30;
this.count = 10;
}
TestB.prototype = new TestA();
TestB.prototype.constructor = TestB;
TestB.prototype.getName = function tb_gn() {
return ' TestB.prototype.getName is called ** ';
};
TestB.prototype.getBothNames = function tb_gbn() {
return Object.getPrototypeOf(TestB.prototype).getName.call(this) + this.getName() + ' this object is : ' + JSON.stringify(this);
};
var tb = new TestB();
console.log(tb.getBothNames());
function NewClass() {
var self = this;
BaseClass.call(self); // Set base class
var baseModify = self.modify; // Get base function
self.modify = function () {
// Override code here
baseModify();
};
}
An alternative :
// shape
var shape = function(type){
this.type = type;
}
shape.prototype.display = function(){
console.log(this.type);
}
// circle
var circle = new shape('circle');
// override
circle.display = function(a,b){
// call implementation of the super class
this.__proto__.display.apply(this,arguments);
}
If I understand correctly, you want Base functionality to always be performed, while a piece of it should be left to implementations.
You might get helped by the 'template method' design pattern.
Base = function() {}
Base.prototype.do = function() {
// .. prologue code
this.impldo();
// epilogue code
}
// note: no impldo implementation for Base!
derived = new Base();
derived.impldo = function() { /* do derived things here safely */ }
If you know your super class by name, you can do something like this:
function Base() {
}
Base.prototype.foo = function() {
console.log('called foo in Base');
}
function Sub() {
}
Sub.prototype = new Base();
Sub.prototype.foo = function() {
console.log('called foo in Sub');
Base.prototype.foo.call(this);
}
var base = new Base();
base.foo();
var sub = new Sub();
sub.foo();
This will print
called foo in Base
called foo in Sub
called foo in Base
as expected.
Another way with ES5 is to explicitely traverse the prototype chain using Object.getPrototypeOf(this)
const speaker = {
speak: () => console.log('the speaker has spoken')
}
const announcingSpeaker = Object.create(speaker, {
speak: {
value: function() {
console.log('Attention please!')
Object.getPrototypeOf(this).speak()
}
}
})
announcingSpeaker.speak()
No, you would need to give the do function in the constructor and the do function in the prototype different names.
In addition, if you want to override all instances and not just that one special instance, this one might help.
function MyClass() {}
MyClass.prototype.myMethod = function() {
alert( "doing original");
};
MyClass.prototype.myMethod_original = MyClass.prototype.myMethod;
MyClass.prototype.myMethod = function() {
MyClass.prototype.myMethod_original.call( this );
alert( "doing override");
};
myObj = new MyClass();
myObj.myMethod();
result:
doing original
doing override
function MyClass() {}
MyClass.prototype.myMethod = function() {
alert( "doing original");
};
MyClass.prototype.myMethod_original = MyClass.prototype.myMethod;
MyClass.prototype.myMethod = function() {
MyClass.prototype.myMethod_original.call( this );
alert( "doing override");
};
myObj = new MyClass();
myObj.myMethod();

Categories

Resources