Self invoking function written with 'var name = " in the front - bad practice? - javascript

In my knockout.js project I wrote some self invoking functions like this:
var addMarkers = function () {
ko.utils.arrayForEach(self.sectionList(), function (sectionItem) {
ko.utils.arrayForEach(sectionItem.placeList(), function (placeItem) {
placeItem.marker.addListener('click', function () {
map.panTo(placeItem.marker.getPosition());
});
});
});
}();
The function works without problems, however in JSLint the "var addMarkers" was highlighted as unused variable. That makes me wonder if I should the function like this, or just make anonymous because it is a better practice?:
function addMarkers (){ code to be executed };

Assigning the result of a self-executing function is often useful. In particular, I like to define my main viewmodel this way, because
I don't need a prototype for my viewmodel
I'm not likely to need more than one instance of a viewmodel
The reason you would use a self-executing function is that you need a local scope for whatever you're doing, to isolate it from surrounding scope. The reason you would assign a variable from it is that you want it to return a value you will use later. In your example, neither of these is true.

Related

Calling functions within other functions outside

I've used this ability previously but for some reason, it isn't working and is giving the error below. I am not sure why and it is probably something obviously wrong that I am not seeing.
TypeError: (intermediate value).inside is not a function
Caller is called and runs a new outside function which specifically targets the inside function to run alone leaving the rest of the outside function none of the wiser about inner running.
function caller() {
new outside().inside();
}
(function outside() {
function inside() {...}
})();
caller();
Preferably outside() would be a self invoking function, but I don't think that is even possible.
A function declared inside another function creates a local variable in the scope of that function, it does not create a property on the return value of the function.
If you want the latter, then you have to create it explicitly.
Also note, since you are using the new keyword, that constructor functions are expected to be named with an initial capital letter.
function caller() {
new Outside().inside();
}
function Outside() {
function inside() {
console.log("Inside");
}
this.inside = inside;
}
caller();

Benefit of Immediately-invoked function expression (IIFE) over a normal function

I'm pretty new to javascript and I read about the module pattern to provide some sort of namespace and have both private and public members, for example:
var module = (function() {
var s = "Hello, i'm private and in closure!";
return {
myString : s,
myFunc: function() { alert(s); }
};
})();
I do see the benefits of that, because it gives you some of the advantages of object-oriented programming. But I've seen a lot of examples of an IIFE that doesn't get assigned to a variable. This (as far as I see) has no advantages at all compared to a normal function that you invoke:
1. IIFE
(function() {
var s = "Hello I'm private!";
$('#myButton').on('click', function() {
alert(s);
});
})();
2. Normal function
function Initialize() {
var s = "Hello I'm private!";
$('#myButton').on('click', function() {
alert(s);
});
}
Initialize();
They both have private variables that avoid the need of creating global variables and they both execute without returning any value to a variable.
Although the second one gives you the option of choosing a good name that says a lot more than a potential large IIFE without the name, leaving the reader to find out what's happening. The answer I see everywhere is 'to avoid namespace pollution' but both approaches do that, the first one is just a bit harder to understand?
In short:
What is the benefit of using an IIFE over a normal function that I'm missing? Why should I use them?
Sometimes you need to define and call function at the same time and only once so in this case anonymous function helps you. In such situations giving functions a name and then calling them is just excess.
Further sometimes you wants to create a namespace for your variables. So anonymous functions helps you there too. For example
(function($) {
$.fn.pluginName = function(opt) {
// implementation goes here...
}
}(jQuery));
In above case you can safely use $ as jQuery synonym in your code.
If you define a function with name as shown below, then it will create global variable with function name as you defined.
function myFunction() {
// function code goes here.
}
myFunction();
But if you define it without name then it won't create any global variable and your global namespace will not be polluted.
(function myFunction() {
// function code goes here.
}());
Function with names are useful only when you need to call them from different places in your code.

What is the correct way of calling an internal function using the module pattern in Javascript

I am new to Javascript and am still getting my head round the various ways of creating objects i.e constructor+new, prototypal, functional & parts.
I have created what I think is an object factory using the module pattern and want to know what the correct method of calling an internal method would be. Is it via this or function name.
Here is my module:
function chart() {
function my() {
// generate chart here, using `width` and `height`
}
my.sayHi = function(){
console.log('hi');
my.sayBye();
};
my.sayBye = function(){
console.log('Bye');
};
return my;
}
var test = chart();
test.sayHi();
You can see that the first function calls the second using my.sayBye() or is it better to use this.sayBye(). Both produce the same result and run without error.
The module pattern allows you to dispense with the 'this' variable if you want to. I would probably rewrite the above code to look like this and then the question becomes moot.
function chart() {
var hiCount = 0;
function sayHi(){
console.log('hi');
hiCount++;
sayBye();
};
function sayBye(){
console.log('Bye');
};
return {
sayHi : sayHi,
sayBye: sayBye
};
}
var test = chart();
test.sayHi();
In the above code all is defined within the function chart. As JavaScript's scope is at the function level every time the chart function is called a new set of functions will be defined. And a new set of variables can also be defined that are private to the function as they are defined in the function and are not accessible from outside. I added hiCount as an example of how you could do this. The Module pattern allows privacy in JavaScript. It eats more memory than the prototype pattern though as each time a function is declared it is not shared between other instances of the same class. That is the price you have to pay in Javascript to have class variables that are private. I willingly pay it. Removing 'this' from my code makes it easier to understand and less likely that I will fall into problems of misplaced scope.
Using "this" is better approach because you would be able to bind the function directly to the parent function object.And you dont need to return anything from the function.
where as in your case you are explicitly returning another function
Here is the use of "this" approach
function chart() {
this.sayHi = function(){
console.log('hi');
}
}
var test = new chart();
test.sayHi();
Using this approach you would be able to call anything in the prototype of function "chart"
Eg
chart.prototype.hello = function(){
console.log('hello')
}
So you would be able to call the hello function from the same object(test)

How do I make a nonexistent (non-member, non-global) method invocable without using eval?

Let's start from the code:
function say(name) {
var ghost=function () {
function ghost() {
alert('!');
};
return body;
};
eval("var body=''+"+name+';');
eval(name+('=('+ghost).replace('body', body)+')();');
eval(name+'();');
}
function Baal() {
if ('undefined'===typeof ghost) {
say('Baal');
return;
}
ghost();
}
say('Baal'); // or just Baal();
Looks like that saying the devil's name invoke his presence (well, maybe he needs somebody for spiritual possession) ..
As you can see the ghost doesn't exist along with Baal, but we can invoke it since there're evals in say(name).
say(name) reassigns Baal to its code body as a closure and makes it captured a ghost method, that's how things work. But I'm trying to avoid eval ..
So .. let me reword the question:
How do I make a nonexistent(and not a member or global) method invocable without using eval?
Let me rephrase your question, just to make sure I’ve got it. Given a function, you want to put a new variable in its scope, without that scope being the global scope or a scope shared between the caller and the subject, without using eval (or the equivalent new Function and other hacks depending on the environment).
You can’t.
In the case you just mentioned, you could define one function, base(), that uses arguments.callee.caller.
Don’t do that.
The short answer: You don't.
That scope is not available. If you were to attach the scope then it would be available inside of the scope used. You could then access the method handles. I assume this is not what you were looking for, but here is what that would look like. demo
function say(name){
var methods = {};
methods.Baal = function(){
alert("!");
};
return methods[name];//this could invoke as well: methods[name]()
}
var handle = say('Baal');
handle();
What your evals break down to is something along these lines (although with dynamic content from string building - this is the end result)
function say(name) {
var Baal = (function () {
function ghost() {
alert('!');
};
return function(){
if ('undefined'===typeof ghost) {
say('Baal');
return;
}
ghost();
}
})();
Baal();
}
say('Baal'); // or just Baal();
Note that the meat of what happens here is from the function Baal, namely that it calls a hardcoded ghost() which in turn calls a hardcoded alert. Why go through all of this trouble to access a hardcoded function?
A better way would be to inject this function as a callback which expects some parameters to be injected.
jsFiddle Demo
function say(callback){
var params = "!";
if( typeof callback == "function" ){
callback(params);
}
}
say(function(params){
alert(params);
});
It's very difficult for me to read through your code and figure out what you are trying to accomplish with it, but it appears that you are trying to introduce a variable into the current scope so that you can call it. You cannot do this in javascript with the method that you demonstrated. Scoping only ever "flows down". By that I mean that a variable or function defined within a function will only be available to that function and any other functions defined therein. Your function named ghost will only ever be available within the function where it is defined, regardless of when that function is evaluated.
What you can do, however, is write a function that returns a function. You can then call that function and assign the result to a variable in the scope where you want to expose functionality. Doing that would look something like this.
function defineSpecialAlert() {
return function(name) {
alert(name + "!");
};
}
var newlyDefinedMethod = defineSpecialAlert();
newlyDefinedMethod("Baal");
So if I understand, it seems like you want to create an alias of eval: Something like
#Note this code is not intended as a solution, but demonstrates
#an attempt that is guaranteed to fail.
#
function myAlias(ctx) {
eval.call(ctx, 'var ghost = 42');
}
myAlias(this);
alert(ghost);
Javascript allows many funky sleight-of-hand tricks especially with closures, but this is maybe the one impossible thing that javascript cannot do. I've tried at length to do this exact same thing, and I can tell you that you'll run into nothing but complaints from the browser, saying that eval cannot be re-contexted or aliased in any way.

Reuse function without global variables?

A couple of days ago I have learned on my own example how bad global variables and functions are. So apparently the best solution is NOT to use them, however sooner or later I will need to reuse my variables and functions over and over again.
So my question is: Can I reuse my functions and variables without declaring them globally? Can it be done?
For example, I want to reuse my alertBox function and my containsP variable couple of times:
DEMO: http://jsfiddle.net/ajmyZ/
//I am BAD GLOBAL FUNCTION inside var
//But I am reusable!!!
var alertBox = function () {
alert("Hey I am BAD function!!")
}
$(document).ready(function () {
//I am BAD GLOBAL var
//But I am reusable TOO!!!
var containsP = $("div p:first");
containsP.click(function () {
alert("Hi BAD var HERE!!");
});
$("p").eq(1).click(function () {
alertBox();
});
//I am the NICEST function here
//but I am NOT reusable :(
$("p").eq(2).click(function () {
alert("I am the NICEST function here!!");
});
});
I guess the simplest way to avoid clobbering the global object is just to create your own "application context". You can do that, by creating a self-invoking function which wraps your whole js-code within each file.
(function( win ) {
"use strict";
var still_global_but_only_in_this_anonymous_closure = true;
$(document).ready(function() {
// ...
// accessing the global object:
win.some_global_property = true;
});
}( this ));
Actually, you're already creating such a local context with your anonymous function you pass into .ready(). This is just the more explicit way. That self-invoking method, just calls itself with the global object as argument (where you still can explicitly access global variables). Furthermore, by invoking "use strict"; you're protected from accidently creating global variables alá "Ops_I_Forgot_The_Var_Statment = true;
The code you posted has no global variables. A variable declared inside of a function (in the case of your example, the anonymous document.ready handler) will never be global unless you make one of two mistakes:
forget the var keyword, making an implicit global
explicitly say window.myVar = ...;

Categories

Resources