I came across a custom filter used in angularJS where we are returning a function with a logic for custom filter. Here I'm not able to understand when exactly i should be using closures. I tried to return a function with in a jquery call back function, but the control just doesn't go inside the function body, but the control goes inside the angularJS custom filter. Can someone help me understand the concept.
AngularJS Custom filter Code, where the control goes inside the anonymous function:
app.filter('myFilter', function () {
return function (curItem, txtSearch) {
var results = [];
if (txtSearch && curItem) {
for (i = 0; i < curItem.length; i++) {
// some logic for filter
}
return results;
app.filter('myFilter', function () {
return function (curItem, txtSearch) {
var results = [];
if (txtSearch && curItem) {
for (i = 0; i < curItem.length; i++) {
alert(curItem[i].name);
}
return results;
}
}
});}}});
Jquery function where i'm trying to pass the control with in the return anonymous function although i know like i will be able to do with in just the call back instead of using the closure.
$('div').on('click', function () {
return function () {
alert('');
}
});
I suggest you should first understand what closures are before trying to use them.
I recommend reading You-Dont-Know-JS book on GitHub for getting clarity on this topic. It is very neatly and conceptually explained in this chapter.
After understanding what closures are and what are their advantages, you can yourself identify the situations where to apply it.
Hope it helps!
Related
I've wrote a small example for readability.. I'm trying to get my head around proper js app structure.
I'm new to writing larger js apps. Right now, I've got a constructor, and a whole bunch of prototype functions. I always thought you're NOT supposed to call (or return) from one function to another. But now, at the bottom of my app, I'm instantiating my constructor, then having to call a bunch of functions, as well as build in conditional statements to handle the execution, which seems totally wrong.
This is the idea I've been doing:
function TodaysFood(b, l)
{
this.breakfast = b;
this.lunch = l;
}
TodaysFood.prototype.firstMeal = function()
{
return console.log(this.breakfast);
}
TodaysFood.prototype.secondMeal = function()
{
return console.log(this.lunch);
}
var app = new TodaysFood("eggs", "sandwich");
app.firstMeal();
app.secondMeal();
I'm wondering if this function "linking" is proper?
function TodaysFood(b, l)
{
this.breakfast = b;
this.lunch = l;
}
TodaysFood.prototype.firstMeal = function()
{
return this.secondMeal(this.breakfast);
}
TodaysFood.prototype.secondMeal = function(firstMeal)
{
var twoMeals = [firstMeal, this.lunch];
return this.whatIAte(twoMeals);
}
TodaysFood.prototype.whatIAte = function(twoMeals)
{
return console.log(twoMeals);
}
var app = new TodaysFood("eggs", "sandwich");
app.firstMeal();
Stupid example, but I'm trying to understand how an app should flow. Should I be able to write my whole app in separate, but linked functions, then just kick the whole thing off by instantiating the constructor, and maybe calling one function. Or is the first example more correct -- writing independent functions, then handling the interaction between them after you've instantiate the constructor?
Thanks for any help.
You may want to make it modular, Ala Node.js or within the browser using RequireJS
Here is a slight variation of the second example you could consider, view fiddle
var TodaysFood = function (b, l) {
var self = this;
this.breakfast = b;
this.lunch = l;
this.firstMeal = function () {
console.log(this.breakfast);
return self;
};
this.secondMeal = function () {
console.log(this.lunch);
return self;
}
this.allMeals = function () {
return this.firstMeal().secondMeal();
};
}
var food = new TodaysFood('eggs', 'sandwich');
food.firstMeal().secondMeal().allMeals();
If you plan to use node.js or RequireJS then the above could be modularized by replacing the last two test lines of code with,
module.exports = TodaysFood;
If this is made modular then you would remove the constructor var TodaysFood = function(b, l) { ... and instead accept arguments for b & l within your individual methods like firstMeal & secondMeal. This would make it static and prevent collisions with the constructor values.
I have a basic widget which i can push function calls to (almost like Google analytics, ga.js)
Here is the widget code:
var widget = function () {
function _private_setName(a, callback) {
console.log(a[0]);
callback(a[0]);
}
return{
setName:_private_setName
};
}();
if (window._test) {
for (var i = 0; i < _test.length; i++) {
var method = _test[i].shift();
try {
widget[method].apply(widget, _test);
}
catch(err) { }
}
}
window._test = {
push: function() {
try {
var args = Array.prototype.slice.call(arguments, 0);
var method = args[0].shift();
widget[method].apply(widget, args);
}
catch(err) { }
}
};
So what i can currently do is this:
var _test = _test || [];
_test.push(['setName', 'Todd']);
However i would like to be able to get callbacks from the function setName.
I've tried:
_test.push('setName', 'Todd', function(num) {
console.log("callback called! " + num);
});
But i cannot get it to work, any ideas how i can implement this?
You should change
var method = args[0].shift();
to
var method = args.shift();
After that the callback will be called. Here is a jsfiddle with a working version http://jsfiddle.net/krasimir/pLuad/1/
That's some pretty hanky janky code you've got there to achieve what you're looking to do. A common practice with callback is to use arguments[arguments.length -1], in the function you are passing the callback to, so it's always the "last" argument that will be used as the callback function. Then you say
if(typeof arguments[arguments.length - 1] === 'function'){
arguments[arguments.length - 1](dataToPassToCallback);
}
In your situation, it seems like you are adding a lot of needless abstraction and making this much more difficult than it needs to be. For example, you are declaring a "widget" object/class, and then you are assigning static instances of itself to it ( widget[fnName] = widget.apply()) - so now when you are declaring more widgets, they are all containing references to the other widget methods.
I would imagine what you really want is for Widget class to be it's own thing and for there to be a WidgetManager class or a Widgets class that will then do similar things to what your _test array is doing.
I'm running some code through JSHint and I keep getting the following error:
Don't make functions within a loop.
I tried turning off the warning for 'About functions inside loops' off which does nothing to stop the error from being reported. I have decided to refactor the code, using JSHint's suggestions here, http://www.jshint.com/options/ but I'm still getting the error. I was hoping that somebody could help me to refactor this code slightly so it will pass. Here's a copy of the function:
function setSounds(parent) {
var i,
l;
parent.getElements('.sound').each(function (elem) {
var soundEvents = [];
if (elem.get('fk_click_sound')) {
soundEvents.push('click');
}
if (elem.get('fk_mouseover_sound')) {
soundEvents.push('mouseenter');
}
if (soundEvents.length !== 0) {
for (i = 0, l = soundEvents.length; i < l; i += 1) {
elem.addEvent(soundEvents[i], (function () {
return function (e) {
FKSoundAIR(FKSoundStd[this.get('fk_' + e.type + '_sound')]);
};
})(elem), false);
}
}
});
}
I'm using MooTools. The purpose of this function is to pass a parent element and then apply sound event to all of the children with the class 'sound.' I'm using custom HTML attributes, such as 'fk_click_sound' to feed additional information to the function. I picked up this method of assigning a function within a loop from http://blog.jbrantly.com/2010/04/creating-javascript-function-inside.html.
Any suggestions or resources that you can point me to would be great. Thanks!
You can try something like this:
function make_handler(div_id) {
return function () {
alert(div_id);
}
}
for (i ...) {
div_id = divs[i].id;
divs[i].onclick = make_handler(div_id);
}
You could create the function outside, assign it to a var and use it in your call to addEvent.
As it turns out JS Hint had a bug re: the warning for Looping inside of a function, which they fixed here. Now that this is fixed, this issue is resolved.
I am trying to write a logger object which logs messages to screen. here is my code.
http://github.com/huseyinyilmaz/javascript-logger
in every function that needs to log something, I am writing loggerstart and loggerEnd functions at start and end of my functions. But I want to run thos codes automaticalls for every function. is there a way to modify Function prototype so every function call can run automatically.
(I am not using any javascript framework.)
EDIT: Rewritten the function to make it more modular
Well, this is a creepy way to do it, but I use this way sometimes when I need overriding some functions. It works well, allows any kind of customization and easy to understand (still creepy).
However, you will need to have all your functions stored in some kind of global object. See the example for details.
function dynamic_call_params(func, fp) {
return func(fp[0],fp[1],fp[2],fp[3],fp[4],fp[5],fp[6],fp[7],fp[8],fp[9],fp[10],fp[11],fp[12],fp[13],fp[14],fp[15],fp[16],fp[17],fp[18],fp[19]);
}
function attachWrapperToFunc(object, funcName, wrapperFunction) {
object["_original_function_"+funcName] = object[funcName];
object[funcName] = function() {
return wrapperFunction(object, object["_original_function_"+funcName], funcName, arguments);
}
}
function attachWrapperToObject(object, wrapperFunction) {
for (varname in object) {
if (typeof(object[varname]) == "function") {
attachWrapperToFunc(object, varname, wrapperFunction);
}
}
}
And some usage example:
var myProgram = new Object();
myProgram.function_one = function(a,b,c,d) {
alert(a+b+c+d);
}
myProgram.function_two = function(a,b) {
alert(a*b);
}
myProgram.function_three = function(a) {
alert(a);
}
function loggerWrapperFunction(functionObject, origFunction, origFunctionName, origParams) {
alert("start: "+origFunctionName);
var result = dynamic_call_params(origFunction, origParams);
alert("end: "+origFunctionName);
return result;
}
attachWrapperToObject(myProgram,loggerWrapperFunction);
myProgram.function_one(1,2,3,4);
myProgram.function_two(2,3);
myProgram.function_three(5);
Output will be:
start,10,end,start,6,end,start,5,end
So generally it allows you to wrap each function in some object automatically with a custom written wrapper function.
You could call every function with a wrapper function.
function wrapper(callback) {
loggerstart();
callback();
loggerend();
}
And call it with wrapper(yourfunction);
EDIT: OK, I believe the following solutions are valid:
Use the jQuery AOP plugin. It basically wraps the old function together with the hook into a function sandwich and reassigns it to the old function name. This causes nesting of functions with each new added hook.
If jQuery is not usable for you, just pillage the source code, there did not seem to be any jQuery dependencies in the plugin, and the source is simple and very small.
Have an object describing all hooks and their targets and one to store the initial unmodified function. When adding a new hook, the wrapping would be redone around the original function, instead of re-wrap the the previous wrapping function.
You escape nested functions, and get two objects to handle instead. Potentially, this could also mean easier hook handling, if you add/remove hooks often and out of order.
I'll go with the first, since it's already done, and I don't have performance to worry about. And since the original functions are not affected, even if I switch hooking methods, I'll only need to redo the hook adding, which might be just some simple search&replace operations.
Hi,
Is it possible to create a mechanism, in which function A might have a set of hooks(functions that will execute before/after function A)?
Ideally, function A would not be aware of hooking functionality, so that I do not have to modify the source code of function A to call the hooks. Something like:
A = function(){
alert("I'm a naive function");
};
B = function(){
alert("I'm having a piggyback ride on function A!"+
"And the fool doesn't even know it!");
};
addHook(B, A)//add hook B to function A
A()
//getting alerts "I'm a naive function"/"I'm having a
//piggyback ride on function A! And the fool doesn't even know it!"
I've been trying to hack something up for a couple of hours, but so far no luck.
Might not be pretty but it seems to work...
<script>
function A(x) { alert(x); return x; }
function B() { alert(123); }
function addHook(functionB, functionA, parent)
{
if (typeof parent == 'undefined')
parent = window;
for (var i in parent)
{
if (parent[i] === functionA)
{
parent[i] = function()
{
functionB();
return functionA.apply(this, arguments)
}
break;
}
}
}
addHook(B, A);
A(2);
</script>
Take a look at jQuery's AOP plugin. In general, google "javascript aspect oriented programming".
Very simple answer:
function someFunction() { alert("Bar!") }
var placeholder=someFunction;
someFunction=function() {
alert("Foo?");
placeholder();
}
This answer is not definitive, but rather demonstrative of a different technique than those offered thus far. This leverages the fact that a function in Javascript is a first-class object, and as such, a) you can pass it as a value to another function and b) you can add properties to it. Combine these traits with function's built-in "call" (or "apply") methods, and you have yourself a start toward a solution.
var function_itself = function() {
alert('in function itself');
}
function_itself.PRE_PROCESS = function() {
alert('in pre_process');
}
function_itself.POST_PROCESS = function() {
alert('in post_process');
}
var function_processor = function(func) {
if (func.PRE_PROCESS) {
func.PRE_PROCESS.call();
}
func.call();
if (func.POST_PROCESS) {
func.POST_PROCESS.call();
}
}
The following function will give you before and after hooks that can be stacked. So if you have a number of potential functions that need to run before the given function or after the given function then this would be a working solution. This solution does not require jQuery and uses native array methods (no shims required). It should also be context sensitive so if you are calling the original function with a context if should run each before and after function likewise.
// usage:
/*
function test(x) {
alert(x);
}
var htest = hookable(test);
htest.addHook("before", function (x) {
alert("Before " + x);
})
htest.addHook("after", function (x) {
alert("After " + x);
})
htest("test") // => Before test ... test ... After test
*/
function hookable(fn) {
var ifn = fn,
hooks = {
before : [],
after : []
};
function hookableFunction() {
var args = [].slice.call(arguments, 0),
i = 0,
fn;
for (i = 0; !!hooks.before[i]; i += 1) {
fn = hooks.before[i];
fn.apply(this, args);
}
ifn.apply(this, arguments);
for (i = 0; !!hooks.after[i]; i++) {
fn = hooks.after[i];
fn.apply(this, args);
}
}
hookableFunction.addHook = function (type, fn) {
if (hooks[type] instanceof Array) {
hooks[type].push(fn);
} else {
throw (function () {
var e = new Error("Invalid hook type");
e.expected = Object.keys(hooks);
e.got = type;
return e;
}());
}
};
return hookableFunction;
}
Here's what I did, might be useful in other applications like this:
//Setup a hooking object
a={
hook:function(name,f){
aion.hooks[name]=f;
}
}a.hooks={
//default hooks (also sets the object)
};
//Add a hook
a.hook('test',function(){
alert('test');
});
//Apply each Hook (can be done with for)
$.each(a.hooks,function(index,f){
f();
});
I don't know if this will be useful. You do need to modify the original function but only once and you don't need to keep editing it for firing hooks
https://github.com/rcorp/hooker