Javascript: How to access properties and method of IIFE - javascript

I have this code and wondering how can we access properties and method of IIFE
var app = (function () {
function app() {
this.name = 'fasf';
}
app.prototype.greeting = function () {
this.a = 'hello world';
console.log(name);
window.alert('hello world');
};
app.prototype.sayhello = function () {
var j = 't';
console.log(this.a);
};
return app;
}());
also about this piece of code
var t = (function greet(name){
name = name || 'enter your name'
console.log('Hello ' + name);
})();

With the code you have, you can just do this:
// create an instance of the app object
var a = new app();
// call methods on it
a.greeting();
a.sayhello();
Your IIFE returns the internal app constructor function and then assigns that to a variable named app. So you can then do new app() to create an instance of that object. Once you create an instance of that object, you can then call any of the methods on the prototype.
In your second IIFE, nothing is returned from the IIFE so t is undefined.
The IIFE itself does not have properties and methods. That's just an immediately invoked function expression. In your first one, it returns a constructor function which is then assigned to a variable so that variable can be used to create objects with that constructor function. There are no properties or methods of the IIFE itself.

The way the IIFE pattern works is that you use local variables for the stuff you want to keep private. Local variables are are only visible inside the function they were defined in they cannot be read or written from anywhere else in the program.
If you want to expose things inside the IIFE outside the IIFE one way to do it is via the return value of the immediately-invoked function:
var stuff = (function(){
// These variables and functions are not
// visible from the outside:
var myvar1 = "Hello";
var myvar2 = "World";
var func1(){
return myvar1 + " " + myvar2;
}
// But we can return a record that contains a
// reference to our private functions, making them
// visible outside this block.
return {
thefunc: func1
}
}());
//Now we can call the "thefunc" function we exported
console.log( stuff.thefunc() );
I made sure to not repeat any variable names to avoid confusion.
In your first example, there isn't much of a point to using the IIFE pattern since there are no local variables that you are making private. You could have just defined the app function outside the IIFE and it would have worked the same.
The second case could have been written more clearly by putting the function in a separate line:
function greet(name){
name = name || 'enter your name'
console.log('Hello ' + name);
}
var t = greet();
Not only is it a bit weird to immediately invoke a named function but in your particular example, the "default argument value" pattern suggests that this function was designed to be called multiple times, sometimes passing the "name" argument and sometimes not passing it (in which case it defaults to the "enter your name" string.

When using IIFE pattern (closure) you usually keep local variables and function private as properly mentions by hugomg's answer.
In case you need to selectively make public some specific property you could consider using "The Revealing Module Pattern" instead, more info here.
Below a simple example showing this pattern:
var app = (function () {
var privateVar = 'hello world';
function sayhelloPrivate() {
console.log(privateVar);
}
function sayhelloPublic() {
console.log(privateVar);
}
// reveal public pointers to
// private functions and properties
return {
sayhello : sayhelloPublic
};
})();
app.sayhello();
//app.sayhelloPrivate(); this will not work as function is private and not visible outside module

Related

Javascript: Assigning a Private Method to Private Variable

So I'm having some JavaScript issues. I'm not a pro, and don't understand why this does not work. All I am trying to do is assign my private variable to the return value of a private function. If I set var xxx=function name() will it execute the function when I reference xxx. Here is my code. Note - var username=getsessionuser(); below.
//Namespace
var SESSIONCONTROLS=SESSIONCONTROLS || {};
SESSIONCONTROLS.APP=SESSIONCONTROLS.APP || {};
SESSIONCONTROLS.APP.User = (function () {
// defined within the local scope
//Private Variable
var username=getsessionuser();
//Privatemethod
var getsessionuser=function(){var mname='My Name'; return mname;}
//Private Property & Method Example
var privateMethod1 = function () { alert("private method 1"); }
var privateMethod2 = function () { alert("private method 2");}
var privateProperty1 = 'foobar';
return {
//Public Method & Nested Namespace examples
//Public Methods
publicMethod1: privateMethod1,
//nested namespace with public properties
properties:{
publicProperty1: privateProperty1,
sessionname:username
},
//another nested namespace
utils:{
publicMethod2: privateMethod2
}
}
})();
This is how its called in another routine.
var name=SESSIONCONTROLS.APP.User.properties.sessionname;
alert(name);
Why doesn't this work?
You've got a simple ordering problem:
var username=getsessionuser();
//Privatemethod
var getsessionuser=function(){var mname='My Name'; return mname;}
JavaScript won't complain about an undefined variable reference, because it treats all the var statements in a function as if they appeared at the very start of the code. However, the initializations in var statements are carried out in the sequence they appear.
Thus, at the point your code attempts to initialize username, the variable getsessionuser is not defined.
If you simply re-order those two statements so that the function is defined first, then that part at least will work.
Alternatively, you could define the function with a function declaration statement:
function getsessionuser() {
var mname = "My Name";
return mname;
}
Then your code will work even if you leave the initialization of username before the function, because function declarations are also "hoisted" up implicitly to the start of the function.
You are calling getsessionuser() before it is defined. Move
var getsessionuser=function(){var mname='My Name'; return mname;}
above
var username=getsessionuser();

Javascript, getting away from 'this' and using local scope

In a typical js class, all calls to member functions must be preceded by this. I was looking at a technique that would let me create a library of inter-dependent STATIC functions and relying on closure/scope to make things a bit easier.
Example:
var Singleton={
//main entry point
// call with fn name, args...
call:function(){
var args=[];
if (arguments.length==0) {
return;
}
// get the fn name
var fn=arguments[0];
var x;
// make args array
for (x=1;x<arguments.length;x++) {
args[args.length]=arguments[x];
}
// I want to get rid of this part
// See below for what I wish
// Here I have access to fns below due to hoisting in js
// so I put them in a map...
var fns={
test:test
// etc, more like this I do not want to type/maintain
}
// ... all so I can do this
// get my function.
var fun=fns[fn];
// instead of that, I would like to "override whitespace" and
// say something like:
// var fun=['fn_name'];
// so I can index into local scope and get a fn
//
// log error if not found
if (typeof fun=='undefined') {
loge('Singleton: function not found:'+fn);
return;
}
// ok, run the function
return fun.apply(window,args);
// the test fn accesses test2() without dot notation
function test(a){
// Note: here in test fn it can access test2()
// without using this.test2() syntax
// as you would in normal objects
var s=test2();
alert(s+' test:'+a);
};
function test2(){
return 'test2';
};
}
}
I was hoping someone more familiar with advances in javascript might have advice on how to emulate an "implied but unnecessary this", it always struck me as strange that this defaults to window, and wouldn't it be nice if this could be pointed to an anonymous object with the local scope attached.
I would love to say ['localObject'] to get something in scope.
Edit:
After seeing some of the responses, I will restate this in the form of a challenge:
What I am looking for is a syntax cheat, a way to, as #Varuna put it, "1. Access static methods without using this variable i.e. they will remain global to one another. 2. Do not want to maintain a local array for static methods and want to achieve with in the local scope itself."
Put differently, I need to have the declared functions Register themselves, but I don't want to state the function name more than once. I suppose #Varuna has a solution using eval to access the local scope.
The following approach wont work:
var o={};
o['fn']=function fn(){};
o['fn2']=function fn2(){};
...because you have to state the fn name twice, but closure is preserved.
And this:
var a=[
function fn(){}
,function fn2(){}
];
Register(a);
Will not work because, AFAIK, you lose closure, ie. fn2 cannot see fn. Which also makes the following declarative style a "this nightmare":
window.MINE={
fn:function fn(){
//this?
// want to say fn2(), not this.fn2(), nor MINE.fn2()
}
,fn2:function fn2(){
//this?
}
,deeper:{
//more
}
};
But something like this might work, if you created a weird property that does the registration on assignment:
var registar=new Registar();
registar.reg=function fn(){};
registar.reg=function fn2(){};
//then access
var fn=registar.getFn(n);
// or
var fn=registar._[n];
The above relies on js properties and having access to fn.name, which is not available in all cases AFAIK.
If I understand correctly, you want to create objects that:
have static members
... which can be accessed without using the this notation
The easiest solution (assuming I've properly understood your query), would be to simply use a closure to store your stratic fields, access them directly by name, then explicitly add them as object members.
Consider:
var myConstructor = (function(){
var foo = 'someStaticField';
var bar = function(){
alert('A static method returns ' + foo);
};
return function(){
return {
foo : foo,
bar : bar
};
};
})();
var myInstance = new myConstructor();
As per my understanding, you want to:
1. Access static methods without using this variable i.e. they will remain global to one another.
2. Do not want to maintain a local array for static methods and want to achieve with in the local scope itself.
You can check whether a method exist using eval.Check Here
Only drawback is that this will be using eval method.
Code will be:
var Singleton = {
//main entry point
// call with fn name, args...
call: function () {
var args = [];
if (arguments.length == 0) {
return;
}
// get the fn name
var fn = arguments[0];
var x;
// make args array
for (x = 1; x < arguments.length; x++) {
args[args.length] = arguments[x];
}
//check whether function exist in local scope and not in global scope
if (typeof eval(fn) !== 'undefined' && typeof window[fn] === 'undefined') {
// ok, run the function
return eval(fn).apply(window, args);
}
else{
// log error if not found
loge('Singleton: function not found:' + fn);
return;
}
// the test fn accesses test2() without dot notation
function test(a) {
// Note: here in test fn it can access test2()
// without using this.test2() syntax
// as you would in normal objects
var s = test2();
alert(s + ' test:' + a);
};
function test2() {
return 'test2';
};
}
}
How about declaring functions that can access each other in separate closure, and exporting them to main method by binding your call method to an object containing the functions? Something like previous post (modified slightly):
var Singleton = {
call: (function() {
// here 'call' is bound to object containig your test functions
// this: {test, test2}
if (0 == arguments.length) return;
// log error if not found
if ('function' != typeof this[arguments[0]]) {
console.warn('Singleton: function not found:' + arguments[0]);
return;
}
// '...index into local scope and get function
// ie. get the function by it's name
return this[arguments[0]].
apply(window, Array.prototype.slice.call(arguments, 1));
// --- or:
// you can explicitly introduce function names to current scope,
// by `eval`-ing them here (not very much preferred way in JavaScript world):
for (var fname in this)
if (this.hasOwnProperty(fname))
eval('var ' + fname + ' = ' + this[fname]);
// and you can reference them directly by using their names
var fn = eval(arguments[0]);
return fn.apply(window, Array.prototype.slice.call(arguments, 1));
}).bind(
(function() {
var _exports = {};
function test (a) {
var s = test2();
alert(s + ' test: ' + a);
}
function test2 () {
return 'test2';
}
_exports['test'] = test;
_exports['test2'] = test2;
return _exports;
})()
)};
Singleton.call('test', 'foo and stuff');
//
previous post:
You are talking about Function#bind functionality that enables 'customizing' function's context. .bind() your call method to required 'local context' like this:
var Singleton = {
//main entry point
// call with fn name, args...
call: (function() {
// here `this` (context) is object bound to `call` method
// not `global` object, which is default for 'unbound' functions
var locals = this; // {fns, shift, loge, isfunc}
var fn;
var fun;
var x;
if (arguments.length == 0)
return;
// get the fn name
fn = locals.shift(arguments);
// '...index into local scope and get a fn'
fun = locals.fns[fn];
// log error if not found
if (!locals.isfunc(fun)) {
locals.loge('Singleton: function not found:' + fn);
return;
}
// ok, run the function
return fun.apply(window, arguments);
// lock `call`'s context to provided object
// and use `this` to reference it inside `call`
}).bind({
fns: (function(_) {
// and you can '...create a library of inter-dependent STATIC functions'
// in this closure and invoke them in `call` method above
_.test = function (a) {
var s = _.test2();
alert(s + ' test: ' + a);
};
_.test2 = function() {
return 'test2';
};
return _;
})({}),
// and create couple of helper methods as well...
isfunc: (function(_getclass) {
_getclass.func = _getclass(_getclass);
return ('function' !== typeof(/foo/)) ?
function(node) {
return 'function' == typeof node;
} :
function(node) {
return _getclass.func === _getclass(node);
};
})(Function.prototype.call.bind(Object.prototype.toString)),
loge: console.warn,
shift: Function.prototype.call.bind(Array.prototype.shift)
}),
};
Singleton.call('test', 'foo and stuff');
// eof
Here's one 'in your face answer', because I really don't like what I see here.
I don't see why you need this kind of construct, you already have that as part of language core.
1. dynamic lookup
you are doing it in a rather 'unprecedented' kind of way,
hashes already do that for you, and it's lightning fast to do a hash search.
If you are eval()-ing random strings to do simple name lookup you really have to
step aside from a keybord for a while... (no offense please)
2. closures
you are saying about 'using closures' which you actualy don't use.
your call function redeclares test functions each time it gets called,
and looks the ('fresh version') functions in it's own variable scope table,
instead of lookig them up in parent scope chains (aka. closures)
outside it's lexical location
3. nfe vs. nfd
ie. named function expressions vs. named function declarations
...you cannot assign a function to a local var and have it retain closure.
It is a feature, you might not be aware of how it works (it tripped me up as well).
check this article out for clarification
4. exceptions
Singleton: function name not found... x4!
Just go ahead and call a function,
interpreter will throw for you anyway if it cannot find/execute
5. eval (aka. ^^)
Singleton.call.ctx.fun = eval(Singleton.call.ctx.fn);
eval takes any string here(#!), and gladly executes ones like:
'for(;;);', or 'while(1);'... forever.
You probably don't want to have any code running unless it was your stuff.
6. arguments handling
It is considered best practice out there to use single (Object) options parameter
to 'fine tune' any significant piece of bundled functionality,
instead of trying to figure that out by type checking provided argument list
Here's, in couple of simple lines, what I (and as I can see #Jimmy Breck-McKye) suggest you should do:
var Singleton.call = (function () {
var funcmap = {
'f_1': function () {},
// etc.
'f_N': function () {},
};
return function (options) {
// options members:
// context, (Object) context, (defaults to global if none is given)
// func, (String) function_name,
// args, (Array) arguments to pass into a function
// this line does everything your 100+ lines long snippet was trying to:
// look's up parent scope for a function, tries to run it
// passing provided data, throws if it gets stuck.
return funcmap[options.func].apply(options.context, options.args);
};
})();
//
Answering my own question here.
The core of the issue is that you cannot assign a function to a local var and have it retain closure.
Consider that when writing a function with global and window scope, this is not necessary to call another function with identical scope. Such is not the case with member functions.
Another way of saying this is that there is no space where your cursor can sit and as you declare a function it automatically gets attached to the current this.
function fn(){}// if we are in global scope, then window.fn becomes defined
// but if we are inside, say, a constructor, simple declaration will not attach
// it to this, but fn is available in scope.
Any assignment on function declaration BREAKS part of the expected closure:
var IdentifierAvailableToClosure=function Unavailable(){}
But assignment after declaration works:
function NowAvailable(){}
var SynonymAvailableToo=NowAvailable;
This is what I meant by not wanting to repeat the name twice to get the mechanism to work.
This fact made me abandon other methods and rely on eval as suggested. Here is a first draft:
// This object is an encapsulation mechanism for a group of
// inter-dependent, static-ish, functions that can call each other
// without a this pointer prefix.
// Calls take the form of:
// Singleton.call(functionName:String [,arg1]...)
// or
// Singleton.call(contextObject:Object, functionName:String [,arg1]...)
// If a context is not provided, window is used.
//
// This type of mechanism is useful when you have defined a group
// of functions in the window/global scope and they are not ready
// to be formalized into a set of classes, or you have no intention
// of doing that
//
// To illustrate the issue, consider that a function
// which is defined in window/global scope
// does not have to use the this pointer to call a function of
// identical scope -- yet in a class member function, the this pointer
// MUST be used
// Therefore, trying to package such functions requires injecting
// the this pointer into function bodies where calls to associater
// functions are made
//
// Usage is primarily for development where one has control over
// global namespace pollution and the mechanism is useful in
// refactoring prior to formalization of methods into classes
var Singleton={
// Main call point
call:function(){
// Bail with error if no args
if (arguments.length==0) {
throw('Singleton: need at least 1 arg');
}
// As all functions in the local scope library below
// have access to the local scope via closure, we want to reduce
// pollution here, so lets attach locals to this call
// function instead of declaring locals
//
// Prepare to call anon fn
Singleton.call.args=arguments;
// Make ctx have args, context object, and function name
Singleton.call.ctx=(function (){// return args,ctx,name
// out
var args=[];
//locals
var x, fn;
// collapse identifier
var a=Singleton.call.args;
// closure object avail to functions, default to window
that=window;
// first real function argument
var arg_start=1;
// first arg must be function name or object
if (typeof a[0]=='string') {// use window ctx
fn=a[0];
// if first arg is object, second is name
}else if (typeof a[0]=='object') {
// assign given context
that=a[0];
// check second arg for string, function name
if (typeof a[1]!='string') {
var err='Singleton: second argument needs to be a fn name'
+' when first arg is a context object';
throw(err)
return;
}
// ok, have a name
fn=a[1];
// args follow
arg_start=2;
}else{
// improper arg types
var err='Singleton: first argument needs to be a string or object';
throw(err)
}
// build args array for function
for (x=arg_start;x<a.length;x++) {
args[args.length]=a[x];
}
// return context
return {
args: args
,that:that
,fn:fn
};
})();
// using function library present in local scope, try to find specified function
try{
Singleton.call.ctx.fun=eval(Singleton.call.ctx.fn);
}catch (e){
console.error('Singleton: function name not found:' + Singleton.call.ctx.fn);
throw('Singleton: function name not found:' + Singleton.call.ctx.fn);
}
// it must be a function
if (typeof Singleton.call.ctx.fun !== 'function') {
console.error('Singleton: function name not found:' + Singleton.call.ctx.fn);
throw('Singleton: function name not found:' + Singleton.call.ctx.fn);
}
// library functions use that instead of this
// that is visible to them due to closure
var that=Singleton.call.ctx.that;
// Do the call!
return Singleton.call.ctx.fun.apply(that, Singleton.call.ctx.args);
//
// cool library of functions below,
// functions see each other through closure and not through this.fn
function test(s){
alert(test2()+' test:'+s);
}
function info_props(){
console.info(this_props());
}
function test2(){
return 'test2';
}
function this_props(){
var s='';
for (var i in that) {
s+=' '+i;
}
return s;
};
}
};

Javascript function object with this reference to itself

I can't seem to find an example of what I'm trying to achieve, although I'm sure it has been done many times before...
I want to create an object which will have a set of properties and member functions but that I can also call directly. In the same way the jQuery object allows you to call $("selector") or $.method(...)
Here's a slimmed down version of what I'm trying to achieve :
var foobar = function(param) {
return "FOO : " + this.lookup(param);
}
foobar.vals = {
1: "one",
2: "two"
};
foobar.lookup = function (param) {
return "BAR : " + this.vals[param];
}
foobar.lookup("1")
// returns "BAR : one"
foobar("1")
// returns error since 'this' points to global scope
// I'd want it to return "FOO : BAR : one"
I've also tried various approaches with function prototype but can't seem to find a method which gives me everything I want...
var foobar = function(param) {
return "FOO : " + foobar.lookup(param);
}
will return you what you want
To understand this, maybe you should take a look at the basics of JavaScript. What are functions how to instanciate an object and what are objects...
To get something like JQuery this is not very difficult, the JQuery main object is simply a function which also has "static" functions.
to declare a variable as function you do
var myFunc = function(){};
to use the variable and extend it with static stuff you simply assign it via
myFunc.staticFunc = function(){};
this doesn't mean that myFunc.staticFunc can be accessed with this in any instance of myFucn because you didn't add the function to the prototype...
To define a class like object which can be instanciated you also define it as function and then extend the prototype. Prototype is your class definition which is used to construct the object's instance:
myFunc = function(){
// ctor
this.lala = "blub";
} ;
myFunc.prototype.objectFunc = function() {
return this.lala;
}
now the object myFunc has a function objectFunc. I have to initialize it with new...
alert(new myFunc().objectFunc());
instances can access itself with this...
To do something like jquery you'll have to do some tricks. Your global variable must be a function which returns an instance of your "real" object, which can implement whatever...
Then you can call your variable as if it is a function, e.g. myFunc()...
Hope the following example makes it more clear how this works: (can be found on jsfiddle)
(function ($) {
var myRealObj = function (outId, printText) {
this.text = printText;
$("#" + outId).append("<li>" + this.text + "</li>");
};
myRealObj.prototype.objectFunc = function () {
return this.lala
};
var myFunc = function (out, txt) {
return new myRealObj(out, txt);
};
myFunc.someFunc = function () {
myFunc("out", "myFunc.someFunc got called");
};
myFunc.static = {};
myFunc.static.someFunc = function () {
myFunc("out", "myFunc.static.someFunc got called");
};
window.$$ = myFunc;
})($);
$$("out", "test obj function");
$$.someFunc();
$$.static.someFunc();
You could add:
foobar = foobar.bind(foobar);
to make the variable refer to a bound version of the function. Any call to the (updated) "foobar" would have this bound to the original function object. You'd also have to mirror the properties if you wanted to get at them directly, which is sort-of a mess.
In the jQuery implementation, there's a separate internal function that handles the basic routing of the master $() function.
Note also that the "global" $.whatever() functions don't really have much to do with the set of methods supported by jQuery instances (objects returned from the $() function). The $ object just serves as a namespace so that those global utilities don't pollute the global (window) namespace.
you declare var foobar = function(param) {... in the global scope so this will always be a window

Dynamically attach a function to grant access to private variables

I'm trying to assign a callback dynamically to an Object of mine, I can't seem to figure out a way to do this while granting this function access to private variables. I've listed the relavant code below with comments where I ran into walls.
Object Factory
function makeObj ( o ) {
function F() {}
F.prototype = o;
return new F();
}
Module
var MODULE = (function(){
var myMod = {},
privateVar = "I'm private";
return myMod;
})();
Various Attempts
myMod.someDynamicFunc = function someDynamicFunc(){
//privateVar === undefined;
alert( privateVar );
}
myMod.someDynamicFunc();
myMod.prototype.someDynamicFunc = function someDynamicFunc(){
//ERROR: Cannot set property 'someDynamicFunc' of undefined
alert(privateVar);
}
myMod.someDynamicFunc();
In this attempt I tried making a setter in the module object... to no avail.
var MODULE = (function(){
var myMod = {},
privateVar = "I'm private";
myMod.setDynamicFunction = function ( func ){
if(func !== undefined && typeof func === "function"){
//Uncaught TypeError:
// Cannot read property 'dynamicFunction' of undefined
myMod.prototype.dynamicFunction = func;
//also tried myMod.dynamicFunction = func;
}
}
return myMod;
})();
var myModule = makeObject( MODULE );
myModule.setDynamicFunction(function(){
alert(privateVar);
});
myModule.dynamicFunction();
Am I just using JavaScript wrong? I'd really like to be able to assign callbacks after the object is initiated. Is this possible?
You can't access the private variable via a callback function set dynamically (since it can't be a closure if it's attached later), but you can set up a system by which you would be able to access the variable:
var MODULE = (function(){
var myMod = {},
privateVar = "I'm private";
myMod.callback = function(fn) {fn(privateVar);};
return myMod;
})();
var someDynamicFunc = function(param) {alert(param);};
myMod.callback(someDynamicFunc);
Of course, this makes it not really private, since anyone could do this. I don't see how it would be possible at all for you to have a "private" variable that you access via dynamically attached functions, without allowing anyone else's dynamically attached functions to have the same privilege (thus making it not really private).
I guess you did not really understand exactly how closures work.
Closures mean that scopes always have access to the outer scope they were defined in.
function Counter(start) {
var count = start;
return {
increment: function() { // has access to the outer scope
count++;
},
get: function() {
return count;
}
}
}
var foo = new Counter(4);
foo.increment();
foo.get(); // 5
The above example returns two closures, both the function increment as well as get keep a reference to the count variable defined in the constructor.
One cannot access count from the outside, the only way to interact with it is via the two "closured" functions.
Remember, closures work by keeping a reference to their outer scopes, so the following does not work:
var foo = new Counter(4);
foo.hack = function() { // is not getting defined in the same scope that the original count was
count = 1337;
};
This will not change the variable count that's inside of Counter since foo.hack was not defined in that scope, instead, it will create or override the global variable count.

When returning an object from a JavaScript constructor function (avoiding 'new') how do I implement public members?

I have begun writing my 'class' type JavaScript functions like the Module Pattern or Revealing Module patten. This avoids the use of 'new' and allows me to define which functions are public in a single place. However, I have been unable to see how to use and access public data members in this pattern.
e.g. the member 'id' below is accessible through myobj.getId(), but myobj.id is undefined.
function setup(){
var myobj = MyObject();
myobj.initialize();
alert(myobj.getId()); // returns 3, as expected
alert(myobj.id); // returns undefined
}
function MyObject(){
var id;
function initialize(){
//do some stuff that initializes data including...
id = 3;
}
return{
initialize:initialize,
id:id,
getId:function(){ return id;}
}
}
Is there no way to get myobj.id to work returning the value that was set in initialize()?
Your problem is that you aren't taking advantage of closure. The line id:id creates a new variable as a member of the object literal you are returning. This has the default value undefined. Then you are assigning the same variable id back to itself, undefined again.
Also, a module is a single object instance, not a factory function. Try something like this:
var myModule = (function(opts) {
var foo = opts.foo || 0, //private variables with default values
bar = opts.bar || 0, // if none are passed in
product = function() { //private method
return (foo * bar);
};
return {
getFoo : function() { //public methods
return foo;
},
fooTimesBar : function() {
return product();
}
}
})({
foo : 5, //options object
bar : 7
});
The core of the module pattern is a self executing anonymous function that declares variables and then returns an object that has privileged access to those variables through closure.
The extra parens at the end, here containing an object literal with some options that get passed in, executes the function, which then returns an object and assigns it to myModule.
Anything declared as a member of that returned object can be accessed publicly. Code in the returned object has access to the variables defined in the anonymous function through closure even after the function has returned. The variables declared in the anonymous function are effectively private. Code outside the function cannot address them except through the methods provided in the returned object.
The whole thing results in a single object instance in myObject. No more than one can be created, which is the definition of a module. A similar approach could be taken the create a factory function however.
The reason is that your variable id is set to undefined by default and it's type will be undefined as well. Now, because undefined type is a primitive one your assignment in the returned object will be a value assignment, not reference. So obj.id will become undefined in the instance and not the same as the id variable in the constructor function.
Now initialize will change the id in the constructor function, and getId will return the same id, but obj.id will refer to the undefined object property.
function MyObject(){
// initialize is used as a public function so
// this will always refer to the current instance
function initialize(){
this.id = 3;
}
return {
// no need to define id here it will
// report undefined on access by default
initialize: initialize,
getId:function(){ return this.id; }
}
}
Run the whole stuff to see it works as expected.
​
You can solve this and still maintain the syntactic sugar of the Revealing module pattern by returning a cached object instead of an anonymous one.
eg:
NAMESPACE.Module = (function () {
//All public members go on api
var api = {}
api.id = 3;
//Private members
var self,
foo,
bar;
/**
#public
*/
api.init = function () {
self = this;
console.log(this); //NAMESPACE.Module
}
/**
#private
*/
function _privateFunction() {
console.log(self); //NAMESPACE.Module
}
return api;
}());

Categories