JavaScript Interview Test Failed - javascript
I recently failed a JavaScript Interview test and couldn't get feedback from the employer on some of the answers, one question in particular. The test was set up with Mocha tests that you had to write the code for it to pass. The Test was :
describe('Step 5', function() {
it('add(2,8)(5).value() => 15', function() {
add(2,8)(5).value()
.should.be.exactly(15).and.be.a.Number;
});
it('add(3, 3, 5)(4)(3, 2).value() => 20', function() {
add(3, 3, 5)(4)(3, 2).value()
.should.be.exactly(20).and.be.a.Number;
});
});
Can someone help with the answer and also explain how/why and possibly when you might use this?
describe('Step 5', function() {
var curry = function (fn) {
return function () {
var args = [],
accumulate = function accumulate() {
args = args.concat(Array.prototype.slice.call(arguments));
return accumulate;
};
accumulate.value = function () {
return fn.apply(null, args);
};
accumulate.apply(null, arguments);
return accumulate;
};
},
add = curry(function () {
return Array.prototype.reduce.call(arguments, function (total, number) {
return total + number;
}, 0);
});
it('add(2,8)(5).value() => 15', function() {
add(2,8)(5).value()
.should.be.exactly(15).and.be.a.Number;
});
it('add(3, 3, 5)(4)(3, 2).value() => 20', function() {
add(3, 3, 5)(4)(3, 2).value()
.should.be.exactly(20).and.be.a.Number;
});
});
Pass a function fn to curry to create a function that, when called, creates a function that accumulates the arguments passed to it over time, and returns itself. You can apply the accumulated arguments to fn by calling the value method attached to the function returned from the function returned from curry.
In this case you can create an add function which adds up an arbitrary number of arguments, and have that receive the accumulated arguments.
Personally I have never had the opportunity to use this technique. But apparently it's a good interview question, so as for the "how, why and when:" Probably to get hired.
In this assignment you were expected to understand partial application of functions. Assume you've got a function with two arguments:
> function plus(a, b) { return a + b }
> plus(1,5)
6
Now, what happens if you call it with less arguments?
> plus(1)
NaN
This isn't particularly helpful - Javascript simply uses the default undefined for the second argument and the function breaks. A smarter way to handle that would be to "freeze" the first argument and when the second one comes, perform the action on both. Then, plus(1)(5) would return 6. To do that, we rewrite plus so that it returns another function that already contains the first argument and accepts the second one:
> function plus(a) { return function(b) { return a + b } }
> plus(1)(5)
6
This process of "freezing" function arguments is called "partial application". Functions that do that automatically when called with less arguments are "curried" functions. In javascript they are not used widely, but most functional languages support them out of the box.
The actual solution to your assignment is slightly more complicated and I leave it as an exercise (see if this answer helps).
I think the "tricky" part of the question is related to the chaining of () in method call. add(2, 8)(5) is not the same thing as add(2, 8, 5). For the first call (thus, in your exercice), your add method should return a function, not the result of the addition.
See more here: Function calling in Javascript with double brackets
Related
Chrome extension: How to settimeout with update [duplicate]
I have some JavaScript code that looks like: function statechangedPostQuestion() { //alert("statechangedPostQuestion"); if (xmlhttp.readyState==4) { var topicId = xmlhttp.responseText; setTimeout("postinsql(topicId)",4000); } } function postinsql(topicId) { //alert(topicId); } I get an error that topicId is not defined Everything was working before I used the setTimeout() function. I want my postinsql(topicId) function to be called after some time. What should I do?
setTimeout(function() { postinsql(topicId); }, 4000) You need to feed an anonymous function as a parameter instead of a string, the latter method shouldn't even work per the ECMAScript specification but browsers are just lenient. This is the proper solution, don't ever rely on passing a string as a 'function' when using setTimeout() or setInterval(), it's slower because it has to be evaluated and it just isn't right. UPDATE: As Hobblin said in his comments to the question, now you can pass arguments to the function inside setTimeout using Function.prototype.bind(). Example: setTimeout(postinsql.bind(null, topicId), 4000);
In modern browsers (ie IE11 and beyond), the "setTimeout" receives a third parameter that is sent as parameter to the internal function at the end of the timer. Example: var hello = "Hello World"; setTimeout(alert, 1000, hello); More details: https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers.setTimeout http://arguments.callee.info/2008/11/10/passing-arguments-to-settimeout-and-setinterval/
After doing some research and testing, the only correct implementation is: setTimeout(yourFunctionReference, 4000, param1, param2, paramN); setTimeout will pass all extra parameters to your function so they can be processed there. The anonymous function can work for very basic stuff, but within instance of a object where you have to use "this", there is no way to make it work. Any anonymous function will change "this" to point to window, so you will lose your object reference.
This is a very old question with an already "correct" answer but I thought I'd mention another approach that nobody has mentioned here. This is copied and pasted from the excellent underscore library: _.delay = function(func, wait) { var args = slice.call(arguments, 2); return setTimeout(function(){ return func.apply(null, args); }, wait); }; You can pass as many arguments as you'd like to the function called by setTimeout and as an added bonus (well, usually a bonus) the value of the arguments passed to your function are frozen when you call setTimeout, so if they change value at some point between when setTimeout() is called and when it times out, well... that's not so hideously frustrating anymore :) Here's a fiddle where you can see what I mean.
I recently came across the unique situation of needing to use a setTimeout in a loop. Understanding this can help you understand how to pass parameters to setTimeout. Method 1 Use forEach and Object.keys, as per Sukima's suggestion: var testObject = { prop1: 'test1', prop2: 'test2', prop3: 'test3' }; Object.keys(testObject).forEach(function(propertyName, i) { setTimeout(function() { console.log(testObject[propertyName]); }, i * 1000); }); I recommend this method. Method 2 Use bind: var i = 0; for (var propertyName in testObject) { setTimeout(function(propertyName) { console.log(testObject[propertyName]); }.bind(this, propertyName), i++ * 1000); } JSFiddle: http://jsfiddle.net/MsBkW/ Method 3 Or if you can't use forEach or bind, use an IIFE: var i = 0; for (var propertyName in testObject) { setTimeout((function(propertyName) { return function() { console.log(testObject[propertyName]); }; })(propertyName), i++ * 1000); } Method 4 But if you don't care about IE < 10, then you could use Fabio's suggestion: var i = 0; for (var propertyName in testObject) { setTimeout(function(propertyName) { console.log(testObject[propertyName]); }, i++ * 1000, propertyName); } Method 5 (ES6) Use a block scoped variable: let i = 0; for (let propertyName in testObject) { setTimeout(() => console.log(testObject[propertyName]), i++ * 1000); } Though I would still recommend using Object.keys with forEach in ES6.
Hobblin already commented this on the question, but it should be an answer really! Using Function.prototype.bind() is the cleanest and most flexible way to do this (with the added bonus of being able to set the this context): setTimeout(postinsql.bind(null, topicId), 4000); For more information see these MDN links: https://developer.mozilla.org/en/docs/DOM/window.setTimeout#highlighter_547041 https://developer.mozilla.org/en/docs/JavaScript/Reference/Global_Objects/Function/bind#With_setTimeout
You can pass the parameter to the setTimeout callback function as: setTimeout(function, milliseconds, param1, param2, ...) eg. function myFunction() { setTimeout(alertMsg, 3000, "Hello"); } function alertMsg(message) { alert(message) }
Some answers are correct but convoluted. I am answering this again, 4 years later, because I still run into overly complex code to solve exactly this question. There IS an elegant solution. First of all, do not pass in a string as the first parameter when calling setTimeout because it effectively invokes a call to the slow "eval" function. So how do we pass in a parameter to a timeout function? By using closure: settopic=function(topicid){ setTimeout(function(){ //thanks to closure, topicid is visible here postinsql(topicid); },4000); } ... if (xhr.readyState==4){ settopic(xhr.responseText); } Some have suggested using anonymous function when calling the timeout function: if (xhr.readyState==4){ setTimeout(function(){ settopic(xhr.responseText); },4000); } The syntax works out. But by the time settopic is called, i.e. 4 seconds later, the XHR object may not be the same. Therefore it's important to pre-bind the variables.
I know its been 10 yrs since this question was asked, but still, if you have scrolled till here, i assume you're still facing some issue. The solution by Meder Omuraliev is the simplest one and may help most of us but for those who don't want to have any binding, here it is: Use Param for setTimeout setTimeout(function(p){ //p == param1 },3000,param1); Use Immediately Invoked Function Expression(IIFE) let param1 = 'demon'; setTimeout(function(p){ // p == 'demon' },2000,(function(){ return param1; })() ); Solution to the question function statechangedPostQuestion() { //alert("statechangedPostQuestion"); if (xmlhttp.readyState==4) { setTimeout(postinsql,4000,(function(){ return xmlhttp.responseText; })()); } } function postinsql(topicId) { //alert(topicId); }
Replace setTimeout("postinsql(topicId)", 4000); with setTimeout("postinsql(" + topicId + ")", 4000); or better still, replace the string expression with an anonymous function setTimeout(function () { postinsql(topicId); }, 4000); EDIT: Brownstone's comment is incorrect, this will work as intended, as demonstrated by running this in the Firebug console (function() { function postinsql(id) { console.log(id); } var topicId = 3 window.setTimeout("postinsql(" + topicId + ")",4000); // outputs 3 after 4 seconds })(); Note that I'm in agreeance with others that you should avoid passing a string to setTimeout as this will call eval() on the string and instead pass a function.
My answer: setTimeout((function(topicId) { return function() { postinsql(topicId); }; })(topicId), 4000); Explanation: The anonymous function created returns another anonymous function. This function has access to the originally passed topicId, so it will not make an error. The first anonymous function is immediately called, passing in topicId, so the registered function with a delay has access to topicId at the time of calling, through closures. OR This basically converts to: setTimeout(function() { postinsql(topicId); // topicId inside higher scope (passed to returning function) }, 4000); EDIT: I saw the same answer, so look at his. But I didn't steal his answer! I just forgot to look. Read the explanation and see if it helps to understand the code.
The easiest cross browser solution for supporting parameters in setTimeout: setTimeout(function() { postinsql(topicId); }, 4000) If you don't mind not supporting IE 9 and lower: setTimeout(postinsql, 4000, topicId); https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout
I know it's old but I wanted to add my (preferred) flavour to this. I think a pretty readable way to achieve this is to pass the topicId to a function, which in turn uses the argument to reference the topic ID internally. This value won't change even if topicId in the outside will be changed shortly after. var topicId = xmlhttp.responseText; var fDelayed = function(tid) { return function() { postinsql(tid); }; } setTimeout(fDelayed(topicId),4000); or short: var topicId = xmlhttp.responseText; setTimeout(function(tid) { return function() { postinsql(tid); }; }(topicId), 4000);
The answer by David Meister seems to take care of parameters that may change immediately after the call to setTimeout() but before the anonymous function is called. But it's too cumbersome and not very obvious. I discovered an elegant way of doing pretty much the same thing using IIFE (immediately inviked function expression). In the example below, the currentList variable is passed to the IIFE, which saves it in its closure, until the delayed function is invoked. Even if the variable currentList changes immediately after the code shown, the setInterval() will do the right thing. Without this IIFE technique, the setTimeout() function will definitely get called for each h2 element in the DOM, but all those calls will see only the text value of the last h2 element. <script> // Wait for the document to load. $(document).ready(function() { $("h2").each(function (index) { currentList = $(this).text(); (function (param1, param2) { setTimeout(function() { $("span").text(param1 + ' : ' + param2 ); }, param1 * 1000); })(index, currentList); }); </script>
In general, if you need to pass a function as a callback with specific parameters, you can use higher order functions. This is pretty elegant with ES6: const someFunction = (params) => () => { //do whatever }; setTimeout(someFunction(params), 1000); Or if someFunction is first order: setTimeout(() => someFunction(params), 1000);
Note that the reason topicId was "not defined" per the error message is that it existed as a local variable when the setTimeout was executed, but not when the delayed call to postinsql happened. Variable lifetime is especially important to pay attention to, especially when trying something like passing "this" as an object reference. I heard that you can pass topicId as a third parameter to the setTimeout function. Not much detail is given but I got enough information to get it to work, and it's successful in Safari. I don't know what they mean about the "millisecond error" though. Check it out here: http://www.howtocreate.co.uk/tutorials/javascript/timers
How i resolved this stage ? just like that : setTimeout((function(_deepFunction ,_deepData){ var _deepResultFunction = function _deepResultFunction(){ _deepFunction(_deepData); }; return _deepResultFunction; })(fromOuterFunction, fromOuterData ) , 1000 ); setTimeout wait a reference to a function, so i created it in a closure, which interprete my data and return a function with a good instance of my data ! Maybe you can improve this part : _deepFunction(_deepData); // change to something like : _deepFunction.apply(contextFromParams , args); I tested it on chrome, firefox and IE and it execute well, i don't know about performance but i needed it to be working. a sample test : myDelay_function = function(fn , params , ctxt , _time){ setTimeout((function(_deepFunction ,_deepData, _deepCtxt){ var _deepResultFunction = function _deepResultFunction(){ //_deepFunction(_deepData); _deepFunction.call( _deepCtxt , _deepData); }; return _deepResultFunction; })(fn , params , ctxt) , _time) }; // the function to be used : myFunc = function(param){ console.log(param + this.name) } // note that we call this.name // a context object : myObjet = { id : "myId" , name : "myName" } // setting a parmeter myParamter = "I am the outer parameter : "; //and now let's make the call : myDelay_function(myFunc , myParamter , myObjet , 1000) // this will produce this result on the console line : // I am the outer parameter : myName Maybe you can change the signature to make it more complient : myNass_setTimeOut = function (fn , _time , params , ctxt ){ return setTimeout((function(_deepFunction ,_deepData, _deepCtxt){ var _deepResultFunction = function _deepResultFunction(){ //_deepFunction(_deepData); _deepFunction.apply( _deepCtxt , _deepData); }; return _deepResultFunction; })(fn , params , ctxt) , _time) }; // and try again : for(var i=0; i<10; i++){ myNass_setTimeOut(console.log ,1000 , [i] , console) } And finaly to answer the original question : myNass_setTimeOut( postinsql, 4000, topicId ); Hope it can help ! ps : sorry but english it's not my mother tongue !
this works in all browsers (IE is an oddball) setTimeout( (function(x) { return function() { postinsql(x); }; })(topicId) , 4000);
if you want to pass variable as param lets try this if requirement is function and var as parmas then try this setTimeout((param1,param2) => { alert(param1 + param2); postinsql(topicId); },2000,'msg1', 'msg2') if requirement is only variables as a params then try this setTimeout((param1,param2) => { alert(param1 + param2) },2000,'msg1', 'msg2') You can try this with ES5 and ES6
setTimeout is part of the DOM defined by WHAT WG. https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html The method you want is:— handle = self.setTimeout( handler [, timeout [, arguments... ] ] ) Schedules a timeout to run handler after timeout milliseconds. Any arguments are passed straight through to the handler. setTimeout(postinsql, 4000, topicId); Apparently, extra arguments are supported in IE10. Alternatively, you can use setTimeout(postinsql.bind(null, topicId), 4000);, however passing extra arguments is simpler, and that's preferable. Historical factoid: In days of VBScript, in JScript, setTimeout's third parameter was the language, as a string, defaulting to "JScript" but with the option to use "VBScript". https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa741500(v%3Dvs.85)
You can try default functionality of 'apply()' something like this, you can pass more number of arguments as your requirement in the array function postinsql(topicId) { //alert(topicId); } setTimeout( postinsql.apply(window,["mytopic"]) ,500);
//Some function, with some arguments, that need to run with arguments var a = function a(b, c, d, e){console.log(b, c, d, e);} //Another function, where setTimeout using for function "a", this have the same arguments var f = function f(b, c, d, e){ setTimeout(a.apply(this, arguments), 100);} f(1,2,3,4); //run //Another function, where setTimeout using for function "a", but some another arguments using, in different order var g = function g(b, c, d, e){ setTimeout(function(d, c, b){a.apply(this, arguments);}, 100, d, c, b);} g(1,2,3,4);
#Jiri Vetyska thanks for the post, but there is something wrong in your example. I needed to pass the target which is hovered out (this) to a timed out function and I tried your approach. Tested in IE9 - does not work. I also made some research and it appears that as pointed here the third parameter is the script language being used. No mention about additional parameters. So, I followed #meder's answer and solved my issue with this code: $('.targetItemClass').hover(ItemHoverIn, ItemHoverOut); function ItemHoverIn() { //some code here } function ItemHoverOut() { var THIS = this; setTimeout( function () { ItemHoverOut_timeout(THIS); }, 100 ); } function ItemHoverOut_timeout(target) { //do something with target which is hovered out } Hope, this is usefull for someone else.
As there is a problem with the third optonal parameter in IE and using closures prevents us from changing the variables (in a loop for example) and still achieving the desired result, I suggest the following solution. We can try using recursion like this: var i = 0; var hellos = ["Hello World1!", "Hello World2!", "Hello World3!", "Hello World4!", "Hello World5!"]; if(hellos.length > 0) timeout(); function timeout() { document.write('<p>' + hellos[i] + '<p>'); i++; if (i < hellos.length) setTimeout(timeout, 500); } We need to make sure that nothing else changes these variables and that we write a proper recursion condition to avoid infinite recursion.
// These are three very simple and concise answers: function fun() { console.log(this.prop1, this.prop2, this.prop3); } let obj = { prop1: 'one', prop2: 'two', prop3: 'three' }; let bound = fun.bind(obj); setTimeout(bound, 3000); // or function funOut(par1, par2, par3) { return function() { console.log(par1, par2, par3); } }; setTimeout(funOut('one', 'two', 'three'), 5000); // or let funny = function(a, b, c) { console.log(a, b, c); }; setTimeout(funny, 2000, 'hello', 'worldly', 'people');
// These are three very simple and concise answers: function fun() { console.log(this.prop1, this.prop2, this.prop3); } let obj = { prop1: 'one', prop2: 'two', prop3: 'three' }; let bound = fun.bind(obj); setTimeout(bound, 3000); // or function funOut(par1, par2, par3) { return function() { console.log(par1, par2, par3); } }; setTimeout(funOut('one', 'two', 'three'), 5000); // or let funny = function(a, b, c) { console.log(a, b, c); }; setTimeout(funny, 2000, 'hello', 'worldly', 'people');
I think you want: setTimeout("postinsql(" + topicId + ")", 4000);
You have to remove quotes from your setTimeOut function call like this: setTimeout(postinsql(topicId),4000);
Answering the question but by a simple addition function with 2 arguments. var x = 3, y = 4; setTimeout(function(arg1, arg2) { return () => delayedSum(arg1, arg2); }(x, y), 1000); function delayedSum(param1, param2) { alert(param1 + param2); // 7 }
Why does the syntax func1(func2)(parameters); work and what is it called?
From the book Eloquent Javascript Third Edition, chapter 5. I can't seem to find this construct 'f()()' in my research and I would like to learn more about it. I expected to be able to use noisy(Math.min(3, 2, 1)); but there is no output when doing that. However, the book example works as intended. But how? Book example: function noisy(f) { return (...args) => { console.log('calling with', args); let result = f(...args); console.log('called with', args + ', returned', result); return result; }; } noisy(Math.min)(3, 2, 1);
f()() invokes a function named f, which presumably returns a function - then, the final () invokes that returned function. Eg const f = () => { console.log('first invoke'); return () => console.log('second invoke'); }; const returnedFn = f(); console.log('----'); returnedFn(); f()() is like the above, except that it doesn't store returnedFn in a variable - rather, it just executes the returnedFn immediately. That's the same sort of thing that noisy is doing - it returns a function, so if you want to call the returned function immediately without storing the returned function anywhere, put another () after calling noisy. The issue with noisy(Math.min(3, 2, 1)) is that it's calling Math.min immediately - the interpreter simplifies this to noisy(1) before calling noisy, so noisy doesn't see anything about the Math.min or the arguments it was called with. (But the whole point of the noisy function is to log both the input and output of a function)
noisy() takes a function as an argument (it is evident by the line let result = f(...args);). Math.min(3, 2, 1) resolves to a value, not a function which it why it doesn't work when passed into noisy(). All that f()() means is that the function f returns a function, which itself is then executed. It might be easier to understand if we break it down like this: let g = f(); let result = g();
noisy takes a function as an argument and also returns one. Whenever you try noisy(Math.min(3, 2, 1)); you pass result of Math.min(3, 2, 1) to noisy which is the same as calling noisy(1). You could also split the confusing instruction into two: let noisyMin = noisy(Math.min); noisyMin(3, 2, 1); Basically you just get a function as a result of noisy(Math.min) and then you call it right away. f()() is only possible if f() returns a function.
Explain the example with a callback (fat arrow function) as a function argument
I'm doing the Udemy course ES6 Javascript: The Complete Developer's Guide Stephen Grider on my own. Most of the first 4 sections were too easy so I've been doing all the exercises with fat arrow functions (which are new to me and not covered so far in the course) to make it more interesting. However, when I got to Coding Exercise 8: Challenging! Implementing 'reject', I could not figure out how to do it with fat arrow functions. The challenge is to create a function called 'reject' that works in the opposite way to Array.filter. Conceptually, that's easy - just use !. Being stumped, I found a proposed solution using fat arrow functions that works. Here it is: const numbers = [10, 20, 30]; function reject(array, iteratorFunction) { return array.filter(arrItem => !iteratorFunction(arrItem)) } reject(numbers, num => num > 15); I do not understand it. Can someone explain what's going on here? Also, is there a better implementation using fat arrow functions?
To understand the example one needs familiarity and usage of callback functions, anonymous functions, and arrow syntax. Consider the code: function reject(array, iteratorFunction) { return array.filter(arrItem => !iteratorFunction(arrItem)); } The definition of Array filter: The filter() method creates a new array with all elements that pass the test implemented by the provided callback function. What is a callback function? A callback function is a function passed into another function as an argument, which is then invoked inside the outer function to complete some kind of routine or action. This invoking happens when the function with its body (code) is actually passed during invocation. The following code is a callback function: arrItem => !iteratorFunction(arrItem) The function returns a boolean. The function is written as arrow syntax. This can also be written as: function(arrItem) { return !iteratorFunction(arrItem); } iteratorFunction is also a callback function, which returns a boolean. The '!' operator makes the returned boolean negated (turns true to false and vice-versa). So, the following reject function code works similarly: function reject(array, iteratorFunction) { return array.filter(function(arrItem) { return !iteratorFunction(arrItem); }); } -the following is same as above- function reject(array, iteratorFunction) { let myCallback = function(arrItem) { return !iteratorFunction(arrItem); }; return array.filter(myCallback); } iteratorFunction is callback function In the example, consider this code: num => num > 15 The code is an arrow syntax of a callback function. This can also be written as: function(num) { return num > 15; } That means the code: let result = reject(numbers, num => num > 15); -can also be written as- let result = reject(numbers, function(num) {return num > 15}); -can also be written as- let myCallback = function(num) { return num > 15; } let result = reject(numbers, myCallback); The result is: [ 10 ]
num => num > 15 translates to the following anonymous function function(num){ return num > 15 } If you have only one argument, you don't need to provide round brackets and if you are returning an expression , you can skip the curly braces and writing "return" Once , the function syntax is clear,then it is just about passing the function as an argument to reject and providing values of the array as the argument to the anonymous function.
Invoking function in JavaScript [duplicate]
This question already has an answer here: Anonymous function declaration shorthand javascript (1 answer) Closed 7 years ago. This is the code I have got, var MyNameSpace.ShoppingList = { addItem: function (itemName, functionName, listName) { $("<li>", { text: itemName }) .on("click", functionName) .appendTo($("#" + listName)); }, }; then in another module, var MyNameSpace.ModuleX = { init: function () { MyNameSpace.ShoppingList.addItem("Get Eggs From Market", alert("Run Me when listItemClicked"), "shoppingpoplist"); }, }; Question I want alert("Run Me when listItemClicked") to run only when listitem is clicked... I already know changing it to this helps, MyNameSpace.ShoppingList.addItem("Get Eggs From Market", function () { alert("Run Me when listItemClicked"); }, "shoppingpoplist"); But above solution makes my code very long, so there's no point for me adding a separate addListItem, can I solve above issue with least number of code ? Do I must need to add function () {}... either where alert is called or in the addListItem method itself If it's common practice to do so, then am I on right track of putting addItem in a separate method here ?
With ES6, you get arrow functions, which shorten things considerably: MyNameSpace.ShoppingList.addItem("Get Eggs From Market", () => alert("Run Me when listItemClicked"), "shoppingpoplist"); // ^^^^^ equivalent to function() { return ... } If you can't use arrow functions (which are supported in latest versions of Chrome and Firefox, but not IE11 and below), you can do something like this if you really want: function handleWithAlert(msg) { return function() { alert(msg); }; } MyNameSpace.ShoppingList.addItem("Get Eggs From Market", handleWithAlert("Run Me when listItemClicked"), "shoppingpoplist"); handleWithAlert() will return a function, which is what's expected to be passed as the first parameter. So you get a generic event handler generator for alert messages.
The syntax alert(..) will call alert immediately and pass its return value into addItem. What you need instead is to pass a function that when called will execute alert(..). There are pretty much three options for this: function () { alert(..); } or: alert.bind(null, '..') or: function callback() { alert(..); } addItem(.., callback) Take your pick. It doesn't get any shorter.
Identify the pattern of this javascript function
this is a brief pattern of a javascript function which I am not able to understand. this is as seen here: https://github.com/g13n/ua.js/blob/master/src/ua.js. Note: This an edited version as per HugoT's response to my original question's answer. function D(arg) { return function () { return arg > 10; //arg is captured in this function's closure } }; object = { x: D(11), y: D(9), z: D(12) }; SO how does this structure work? I can see the return is an object. But I cant put the things together. Is this a closure pattern? Can anyone explain the flow?
Yes this is a closure pattern. Any arguments passed to D are captured in the closures of the function returned from D. However what you have written is not the same as in the code you linked. This is the important part of the code you linked simplified function D(arg) { return function () { return arg > 10; //arg is captured in this function's closure } }; object = { x: D(11), y: D(9), z: D(12) }; The values 11, 9 and 12 will be captured in the functions object.x, object.y and object.z. Thus object.x() will return true while object.y will return false because 9 > 10 is false. object.z() will return true because 12 > 10
Let's break down ua.js to see what's going on. The outermost layer of the onion is an anonymous function: var UA = (function (window, navigator) { /* anonymous function contents */ }(window, navigator)); So UA is set to the return value of this anonymous function. So what does the anonymous function do? It sets a variable ua. var ua = (window.navigator && navigator.userAgent) || ""; It defines a function detect which returns an anonymous function which tests the contents of ua against pattern. function detect(pattern) { return function () { return (pattern).test(ua); }; } Note that calling detect(/something/) does not return the value of (/something/).test(ua). It simply returns a closure that will perform the test on demand. Now we hit the return value of our outer anonymous function, which looks like this (I've chopped out the comments): return { isChrome: detect(/webkit\W.*(chrome|chromium)\W/i), isFirefox: detect(/mozilla.*\Wfirefox\W/i), isGecko: detect(/mozilla(?!.*webkit).*\Wgecko\W/i), ... whoami: function () { return ua; } } This is returning an instance of Object which contains a number of functions (isChrome etc), and those functions are the closures created by calls to detect(). This means that the execution of those (pattern).test(ua) checks are deferred until someone actually calls UA.isChrome() and so on. You could imagine another approach where all the tests are performed up front, and UA becomes an Object containing a set of flags. This would have had the (probably fairly tiny) overhead of executing pattern matches that you as the developer are not interested in.