Invoke local function in a global function fashion? - javascript

Is it possible to invoke a non-global function, in a global function fashion? (i.e. without using a qualifier)
e.g.
var lib = {
notGlobalFn: function(){ /*...*/ }
};
var foobar = function(){
notGlobalFn();
};
foobar();
I can think of three solutions myself (listed below), but I was hoping there would be another solution which didn't use global functions OR this. context OR subfunctions. Are there any other ways to do this? (Or have I put too many restrictions/am I being a pedant?)
My focus is on brevity and being able to define the foobar function, outside of the context of the lib (i.e. so I can define a library, and let people use it in a local context fashion).
Test: http://jsbin.com/denawa/5/edit?javascript,console
Solution #1: - use a subfunction
Rejected because foobar is integrated into the lib.
var lib = function(){
var notGlobalFn = function(){ /*...*/ }
return {
foobar: function(){
notGlobalFn();
}
}
};
lib().foobar()
Solution #2: - set/unset global function
Rejected because global functions are used.
notGlobalFn = lib.notGlobalFn
foobar();
notGlobalFn = undefined
Solution #3: - use context
Rejected because they're using qualifiers.
var foobar = function(){
this.notGlobalFn();
};
foobar.call(lib);
OR
var foobar = function(){
lib.notGlobalFn();
};
foobar();
All in all, if I had to choose one of the above methods, I'd go with Solution #2.
**EDIT**
Another Solution: - use a local variable (extension of Solution #3).
var foobar = function(){
var notGlobalFn = lib.notGlobalFn
notGlobalFn();
};
And Another Solution: - add notGlobalFn to 'this' (I didn't think this would work).
function init(scope){
scope.notGlobalFn = lib.notGlobalFn
}
var foobar = function(){
init(this)
notGlobalFn()
};

This is the solution I ended up going with. Not sure why this is getting downvoted/closed, no-one has asked for clarification!
function init(scope){
scope.notGlobalFn = lib.notGlobalFn
}
var foobar = function(){
init(this)
notGlobalFn()
};

Related

Dynamically calling constructor from IIFE

Consider the following:
function windowTest() { }
(function () {
function test() { }
var test1 = new test(); // Works fine.
var test2 = new window["windowTest"](); // Works since windowsTest is declared globally.
var test3 = new window["test"](); // Fails since in an IIFE.
// How can I create a testObj if I only have the string "test"?
})();
Basically, I want to create an object whose function was declared in an IIFE.
The reason
var test3 = new window["test"]();
fails is because test was not declared globally. If you want to access items declared directly within the IIFE, as you know, you can access them by name.
new test();
Another way is to store your function inside of some kind of object then access that object like you did with window. This is almost always the solution to these kinds of problems.
(function() {
var context = {
test: function() {
console.log('new test');
}
};
var test = new context['test']();
})();
The last way uses eval. eval is almost always a really bad idea. Really, it should be avoided unless you're abusing the language just for the sake of interest. But you can use it in this case.
(function() {
function test() {
console.log('new test');
}
var test = eval('new test()');
})();
You can bind your functions to this:
function(){
//your code using
this.test("Hi");
this["test"]("Hi");
}.call({
//function declarations:
test:window.alert,
});
Still an IIFE so it wont work in the global context :
this.test("Hi");//reference Error

node.js: Understanding object prototype

There may be several duplicate to this question based on the title of question, but I have a very specific scenario.
I am building a node module sample code below
var myModule = function() {
// do something init
};
myModule.prototype.a = 10;
myModule.prototype.b = 20;
myModule.prototype.method1 = function() {
// in this method I can access a and b using this
this.a
this.b
};
myModule.prototype.method2 = function() {
// I can call method1 here
this.method1();
};
This will works fine for below case mentioned
var myModule = require('myModule');
var instance = new myModule();
calling method2 on instance will work fine
instance.method2 // this should work fine
Now suppose I am passing method2 as a callback function to express or any other function like below
someobject.performsomeasync(instance.method2); // this will fail
As far as I understood about JavaScript prototype is that the above will fail because in that case this will refer to caller object which is not instance
How to make it work ?
And what I am doing is considered a good coding practise ?
You can provide this through the bind method:
someobject.performsomeasync(instance.method2.bind(instance));
Another solution:
someobject.performsomeasync(function() {
instance.method2();
});
UPD1
Following our discussion, you want that methods of your object always
will be executed in context of object instance. Then you can do:
var myModule = function() {
this.method1 = method1.bind(this);
this.method2 = method2.bind(this);
};
myModule.prototype.a = 10;
myModule.prototype.b = 20;
function method1() {
// in this method I can access a and b using this
this.a
this.b
};
function method2() {
// I can call method1 here
this.method1();
};
But this is very bad style. Users of your library are javascript developers. So they must know if you passes callback like someobject.performsomeasync(instance.method2) you just passes method of the object, not context. So they must use bind to provide context.
PS By the way I recommend you not to defined properties of object in your prototype. Define just methods (maybe also constants). It's very error prone. For example if your property is object, then someone can write next code:
instance.someobject.a = 10;
and he'll change a for someobject property for all instances.

The meaning of `this` in JS template method pattern

Why does the marked line fail to find protectedACMember?
var Module = (function (ns) {
function AbstractClass() {
this.protectedACMember = "abstract";
this.abstractPublicACMethod = function (input) {
this.methodToImplement();
}
}
ConcreteClass.prototype = new AbstractClass();
function ConcreteClass(){
var privateCCMember = "private CC";
var privateCCMethod = function(){
alert(this.protectedACMember); // cant find protectedACMember
}
this.methodToImplement = function(){
privateCCMethod();
console.log('Implemented method ');
}
}
ns.ConcreteClass = ConcreteClass;
return ns;
})(Module || {});
//somewhere later
var cc = new Module.ConcreteClass();
cc.abstractPublicACMethod();
are there any good patterns for simulating private, protected and public members? Static/non-static as well?
You should change that part of code like this:
var self = this;
var privateCCMethod = function(){
alert(self.protectedACMember); // this -> self
}
This way you get the reference in the closure.
The reason is, that "this" is a reserved word, and its value is set by the interpreter. Your privateCCMethod is an anonymous function, not the object property, so if you call it simply by privateCCMethod() syntax, this will be null.
If you'd like "this" to be bound to something specific you can always use .call syntax, like this:
privateCCMethod.call(this)
Another way to ensure that this means what you want is to use bind. Bind allows you to ensure a function is called with a specific value of this.
Most newer browsers support it (even IE9!) and there's a workaround for those that don't.
Bind - MDN Documentation
It fails to find protectedACMember because what the this keyword means changes when you enter the function privateCCMethod. A common practice is to store the outer this for use inside the functions:
function ConcreteClass(){
var privateCCMember = "private CC";
// store the outer this
var that = this;
var privateCCMethod = function(){
alert(that.protectedACMember);
}
...
The rest of your questions are fairly loaded and should probably be posted as a separate question.

Where should private methods be placed when using the JavaScript Module pattern?

I've started using the Module pattern in a project of mine. As I understand it, it goes something like this:
var obj = (function(foo){
//Some initialization logic up here.
//Private methods
var privateBazz = function(){
return "I'm known only to this closure!";
}();
//Public methods
return {
publicFoo: foo,
publicBar: function(){
return foo + privateBazz;
}
}
})();
This looked pretty good on paper and, in practice, seems to work reasonably well. Initialization logic at the top is intuitive, then private methods, then public.
I've encountered one issue, though. How should I call publicFoo or publicBar from outside the scope of the return statement and inside the scope of obj's function declaration?
My current solution is to do something like:
var obj = (function(foo){
//Private methods declared early for use.
var privateBazz = function(){
return "I'm known only to this closure!";
}();
var privateBar = function(){
return foo + privateBazz;
};
//Some initialization logic up here.
var dependentOnBar = privateBar();
//Public methods
return {
publicFoo: foo,
publicBar: privateBar
}
})();
This works, but suddenly the declarations of my private variables are placed above my objects private property declarations. The problem becomes exacerbated if I attempt to keep the private function declarations as close to the code which first calls them, so I have just been declaring all the private functions I need at the top, then initializing properties afterwards. Again, this works, but I am used to having code as close to the execution point as possible. So, declaring blocks of private functions at the top is really awkward to me. Does anyone else feel this way, or is this something I just need to get over for JavaScript? Are there any steps I should be taking when I see this happening?
It sounds like you could solve this problem by simply not using object notation to return the module, but rather initialize it and build it as you go. This would go something like this:
var obj = (function(foo){
var self = {};
//Some initialization logic up here.
//Private properties
var foo = "only accessible within this scope";
//Private methods
var privateBazz = function(){
return "I'm known only to this closure!";
}();
//Public Properties
self.publicFoo = foo;
//Public Methods
self.publicBar = function(){
return foo + privateBazz;
};
return self;
})();
here is my solution: if you declare everything before the return as a "private" method and make public those you want to, then you can call your private from within the public and vice versa (in your first sample, your privates can't call the publics as they are not declared at that moment)
var obj = (function() {
// All functions now have direct access to each other
var privateFunc = function() {
return "private "+publicFunc1();
};
var publicFunc1 = function() {
return "public 1 ";
};
var publicFunc2 = function() {
return "public 2 "+publicFunc1();
};
var publicFunc3 = function() {
return "public 3 "+privateFunc();
};
// Return the object that is assigned to Module
return {
publicFunc1: publicFunc1,
publicFunc3: publicFunc3,
publicFunc2: publicFunc2
};
}());
alert(obj.publicFunc3());
If you emulate CommonJS Modules, you can assign properties to the exports object as well as accessing them from elsewhere within the IIFE scope via qualified or unqualified name.
(function (exports, undefined) {
var priv1 = 42;
exports.pubOne = function () {};
var localAlias = function () {};
localAlias(42);
exports.pubTwo = localAlias;
})(window.App);
In this example, Window.App might be my namespaced global object for this module, but you could pass in an empty object or some deeply nested namespace just as easily.

Javascript namespacing - is this particular method good practice?

I'm a javascript newbie, and I've come up with the following scheme for namespacing:
(function() {
var ns = Company.namespace("Company.Site.Module");
ns.MyClass = function() { .... };
ns.MyClass.prototype.coolFunction = function() { ... };
})();
Company.namespace is a function registered by a script which simply creates the chain of objects up to Module.
Outside, in non-global scope:
var my = new Company.Site.Module.MyClass();
I'm particularly asking about the method by which I hide the variable ns from global scope - by a wrapping anonymous function executed immediately. I could just write Company.Site.Module everywhere, but it's not DRY and a little messy compared to storing the ns in a local variable.
What say you? What pitfalls are there with this approach? Is there some other method that is considered more standard?
You dont need to scope classes like that, its only necessary if you have global variables outside of the class. I use this approach...
MyApp.MyClass = function() {
};
MyApp.MyClass.prototype = {
foo: function() {
}
};
Also note that I use a object literal for a cleaner prototype declaration
However if you need to scope global variables then you can do
(function() {
var scopedGlobalVariable = "some value";
MyApp.MyClass = function() {
};
MyApp.MyClass.prototype = function() {
foo: function() {
}
};
})();
Your approach looks fine to me.
However, you can also do this slightly different, by returning the "class" from the self-executing function:
Company.Site.Module.MyClass = (function() {
var MyClass = function() { ... };
MyClass.prototype.foo = function() { ... };
return MyClass;
})();
This strips at least all the ns. prefixes. The namespace function can still be utilized to create the objects, but outside of the self-executing function.

Categories

Resources