Define a function with nested functions and a default function

Consider the following code:

function test() { this.foo = function() { console.log('foo'); return; } this.bar = function() { console.log('bar'); return; } } var action = new test(); action.foo(); //prints 'foo' 

The code above works fine if I need to call the foo or bar action inside the test action. However, the test action itself must be a function being called. I thought it would be great if JavaScript allowed me to create something like this (see below), but, as expected, says:

TypeError: action is not a function

 function test() { this.foo = function() { console.log('foo'); return; } this.bar = function() { console.log('bar'); return; } return function() { console.log('default'); return; }(); } var action= new test(); action(); //prints 'default' action.bar(); //printf 'bar' 

Is it possible to achieve something like this?

+7
javascript
source share
5 answers

It is possible. Just create a function inside and add other properties directly to the function object:

 function test() { var result = function () { console.log('default'); }; result.foo = function() { console.log('foo'); return; } result.bar = function() { console.log('bar'); return; } return result; } var test = new test(); test(); //prints 'default' test.bar(); //printf 'bar' 
+4
source share

In javascript, you can add properties to functions as well. So you can do something like this:

 function test() { function defaultFn() { console.log('default'); } defaultFn.foo = function() { console.log('foo'); return; } defaultFn.bar = function() { console.log('bar'); return; } return defaultFn; } 
+1
source share

While others who pointed out that this is possible, I just wanted to point out that as a rule, it is bad practice that constructor functions return an object that is not an instance created by new .

Looking at your example:

 function Test() { this.foo = function() {} this.bar = function() {} return function() {}(); } var test = new Test(); 

(I renamed your test function to test because it is a convention for uppercase functions that you expect to call with new )

What JS does when calling new Test() is that it creates a new instance of the {} object and passes it to the Test() function as the context of this . By default, this object is also what is returned by calling new .

So what you do is attach the foo and bar functions to this newly created isntance object.

Then you return perform another function, which then returns from the call new Test() instead of an instance of the object that has foo and bar on it ... this object is simply lost / dumped by garbage.

This “returning another object from the constructor function” is bad practice and leads to confusion. Plus this happens:

 function Test() {} var test = new Test(); test instanceof Test; // returns TRUE 

however, if you return something else:

 function Test() { return function() {}; } var test = new Test(); test instanceof Test; // returns FALSE (confusing!!!) 

It would be easier to avoid new and just do:

 function test() { var newFunc = function() { console.log('default'); return; }; newFunc.foo = function() { console.log('foo'); return; } newFunc.bar = function() { console.log('bar'); return; } return newFunc; } var t = test(); t(); // default t.foo(); // foo t.bar(); // bar 
+1
source share

He will select the code below as soon as you instantiate this function. Like _constructor.

 return function() { console.log('default'); return; }(); 
0
source share

I have something like the following:

 function userClass(name, func) { this.name = name; this.func = func; } function test(flag) { this.foo = function() { console.log('foo'); return; } this.bar = function() { alert('bar'); return; } return function() { var obj = {}; obj["bar"] = new userClass("bar", function(){alert('bar');}); alert('default'); return obj; }(); } var test = new test(); //test(); //prints 'default' console.log(test); test.bar.func(); //printf 'bar' 

Jsfiddle

0
source share

All Articles