5

I am trying to create my own plugin for something, however, having trouble with the first step. I would like to have a an object that can take a parameter as default and have other functions in there as well. Please look at the example below on what I am trying to accomplish.

var a = function(str) { console.info(str); }
a = {
    Test: function() { console.info(TestMessage()); },
    TestMessage: function() { return "Test Message"; }
}

Basically, I want the parent object that I can call by itself with a parameter. a("test"); At the same time, I want other functions inside that parent object that can ALSO access other functions within that object. a.Test() -> calls a.TestMessage(), however, not having to write "a." every time while being inside that object.

FerX32
  • 1,407
  • 3
  • 18
  • 28

4 Answers4

6

The problem with your code is you're overwriting the value of a with the second statement. If you want to add properties to the function a refers to, you can do that by assigning to properties on it:

var a = function(str) { console.info(str); };
a.Test = function() { console.info(TestMessage()); };
a.TestMessage = function() { return "Test Message"; };

Now, instead of replacing the function reference in a with a reference to a new object, we're just adding properties to the function object it already refers to.

Note, though, that within Test, you need to qualify TestMessage in order to refer to it correctly:

a.Test = function() { console.info(a.TestMessage()); };
// --------------------------------^^

or if you can rely on a.Test always being called via a, then:

a.Test = function() { console.info(this.TestMessage()); };
// --------------------------------^^^^^

...but the former is more reliable.

Live Example:

var a = function(str) { console.info(str); };
a.Test = function() { console.info(a.TestMessage()); };
a.TestMessage = function() { return "Test Message"; };

a("Direct");
a.Test();
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • I see, thanks. Would this be the best approach for a big plugin? I was thinking something like I would encapsulate it, like it would be a big object and inside would have all the child functions that can call each other without having to write this or parent name. I mean if this way is okay for a big plugin then I'm okay with it. – FerX32 Feb 11 '17 at 15:21
  • @AAA: Sounds to me what you really want is the "revealing module pattern" where you use an IIFE which has private functions inside that can call each other without qualification, and have it return an object with the external interface. – T.J. Crowder Feb 11 '17 at 15:26
  • Yea, that sounds a bit more like it (: However, is there a way to do "default" with that pattern? Like for this one: http://stackoverflow.com/questions/5647258/how-to-use-revealing-module-pattern-in-javascript maybe I can do something like revealed = function(str) and do revealed("direct"), which can do "if (str != undefined) { console.info(str); return; } .. What do you think? – FerX32 Feb 11 '17 at 15:34
  • @AAA: Sure. jQuery's a great example. You just define a function, add properties to it, and return it from the IIFE. `var Thingy = (function() { function foo() { } function bar() { } function baz() { } function Thingy() { } Thingy.prop = function() { }; return Thingy; })();` Within that IIFE, you can call `foo`, `bar`, and `baz` (and `Thingy`) unqualified. They're entirely private, though. – T.J. Crowder Feb 11 '17 at 15:37
1

You can also use revealing module pattern.

To expose only the functions that you are actually planning to call. The helper functions can stay inside your object, without being able to access them from outside.

You can also keep the intial str value in an local variable like, var string = str; and use it in your functions

function A ( str ) {
   console.info( str );

        function test( ) {
            console.info( testMessage( ) );
        }

        function testMessage( ) {
            return "Test Message";
        }

     return {
        test: test
     }
}
var a = new A( "testing" );
a.test();
1

If you want to keep using the simple TestMessage function references, without any prefix, then you could create a closure, in the format of an immediately invoked function expression. Like this:

var a = (function () { // Immediately Invoked Function
    // Define your functions here "at ease":
    function testMessage() { 
        return "Test Message"; 
    }
    function test() { 
        console.info(testMessage()); 
    }
    function main(str) { 
        console.info(str); 
    }
    // Now assign the sub-functions to main:
    main.test = test;
    main.testMessage = testMessage;
    // And return that:
    return main;
})(); // execute immediately so to get the return value

// Test it

a('hello');
a.test();
trincot
  • 317,000
  • 35
  • 244
  • 286
0

You can always return an Object which can have any number of functions. And a function calls another function of its object using this.

I have added a very simple snippet to explain this, please let me know for any clarification.

var parent = createParent();

parent.callAllFunction();


function createParent() {
 return ParentConstructor();
}

function ParentConstructor() {
 var obj = {};
  
 obj.function1 = function1; 
 obj.function2 = function2; 
 obj.function3 = function3; 
 obj.function4 = function4; 
 obj.callAllFunction = callAllFunction;
 
 function function1() {
  console.log('called function1');
 }

 function function2() {
  console.log('called function2');
 }

 function function3() {
  console.log('called function3');
 }

 function function4() {
  console.log('called function4');
 }

 function callAllFunction() {
  this.function1();
  this.function2();
  this.function3();
   this.function4();
 }
 
 return obj;
}

And as you're writing a plugin, you should always isolate your objects/modules from main references to make them more reusable and clean.

Mukul Jain
  • 1,121
  • 11
  • 24