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.
Related
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
_editor: function () {
//retrieve all the editors on the current page
var editors = window.tinymce.editors;
var container = this.element;
//pick one that's associated with current container
$(editors).each(function (i, ed) {
if (ed.id == container.id) {
return ed; // even if this is invoked,
}
});
// undefined is returned
}
I had to change the above code to
_editor: function () {
//retrieve all the editors on the current page
var editors = window.tinymce.editors;
var container = this.element;
var editor;
$(editors).each(function (i, ed) {
if (ed.id == container.id) {
editor = ed; // do not return yet. Store it.
}
});
return editor; // return here
}
I assume this is because of JavaScript's scope characteristics. Could someone explain 1) if this is only inherent in JavaScript 2) what exactly is going on in each functional scope in the above code?
Thank you.
In the first case, you are returning a value from that anonymous function passed to $(editors).each, not the outer function. In the second case you are returning from the outer function.
This is how it works with pretty much any language that allows nested functions. return only returns from the innermost function.
The issue is that you have nested functions. You have the function assigned to the _editor property, and within that you have a function that's being invoked by $.each(). The return statement returns from the closest containing function, so in the first example it's returning from the $.each() iteration function, not the _editor function.
$.each() uses the return value of the iteration function to determine whether to continue looping -- if the function returns false, it stops at that element (similar to using the break; statement in a for or while loop).
Could someone explain 1) if this is only inherent in JavaScript 2) what exactly is going on in each functional scope in the above code?
The code is returning from the function passed to .each(), so it doesn't impact the enclosing function.
You can use $.grep for a cleaner solution.
_editor: function () {
//retrieve all the editors on the current page
var editors = window.tinymce.editors;
var container = this.element;
return $.grep(editors, function (ed, i) {
return ed.id == container.id;
})[0];
}
This is basically a filter. The result will be the items in the collection where you returned a truthy value. And so we just return the first truthy result (index 0 of the result).
It returns from the function called by each:
$(editors).each(function (i, ed) { // <---
if (ed.id == container.id) { |
return ed; // <--- this exits this --
is [this] only inherent in JavaScript[?]
No, many languages which use anonymous functions, also called lambdas, operate like this. A couple of examples are C# and ruby. Calling return exits themselves, rather than the functions they are invoked in.
what exactly is going on in each functional scope in the above code?
$(editors).each(function (i, ed) {
if (ed.id == container.id) {
editor = ed; // do not return yet. Store it.
}
});
The function body is called once for each element ed in $(editors). When the loop exits, the last value for which ed.id == container.id is then stored in editor. The second argument i is the index (0,1,2,3,...) incremented in each iteration.
i have a simple function called Range that creates an array of integers based on start, step and end value...
function Range (start, end, step) {
// default step is 1..
if (step === undefined ) step = 1;
// creating an array...
var arr = [], index = 0;
while(start <= end) {
arr[index] = start ;
index += 1;
start += step;
}
// simple function expressions
var getAll = function () {
return arr ;
};
var getOne = function(n) {
return arr[n] ;
};
// returns a unnamed function ..
return function(i) {
if (i === undefined) { return getAll() ;}
else {return getOne(i); }
}; // not an iife
}
so basically Range is a function which returns a unnamed function which again returns a named function expression declared in the function Range.. err.. i dont know.. something like that...
now the below code...
var first10 = Range (1,10) ; // no new ..() here, so no instance should be created.. only Range is called..
var first10Odd = Range(1,20,2) ; // and Range is called again..
alert(first10); // alerts - function(i) { ... }
alert(first10Odd); // alerts- function(i) { ... }
alert(first10()) ; // alerts - 1,2,3,...10
alert(first10Odd()); // alerts - 1,3,5,...19
alert(first10(0)); // alerts - 1
alert(first10Odd(9)); // alerts- 19
why do the alerts alert as specified in the comments??... i think Range is a just a function and not a object constructor and also no instance was created... shouldn't the local variables of function be destroyed as soon as the function is completed??
or is my logic wrong?? what is going on in the above code?? can anyone please explain....
i have made a fiddle of my code here..
sorry for asking this stupid question..
Welcome to the land of closures in Javascript. They can be very powerful and extremely useful once you understand them. But, if your prior experience is with languages that do not have them, they can feel a bit foreign at first.
Some answers/explanation:
Calling Range(x, y) returns a function that can then be called later.
Because that function that is returned is inside another function scope that has variables, a closure is created.
That closure stays alive (even though the outer function has finished executing) because there is a lasting reference to the inner function saved in your variables and that inner function has a reference to the local variables in the outer function. These references keep the closure from being garbage collected (so it stays alive).
That inner function can then reference the variables in the outer function, including the arguments originally passed to it.
This construct allows you to create these custom functions that have arguments pre-built into them.
The notion of this type of closure only exists in some languages. It does not exist in C++, for example.
When the function returned by calling Range(x,y) is itself executed later, it can use any of the variables that were originally in scope to it.
Each call to Range(x,y) causes a new closure to be created.
getAll and getOne are local variables in the outer function that are assigned a function. They access other local variables in the outer function. All of these are in the previously mentioned closure that is created each time Range() is called.
There is lots written about what a closure is (which you can Google and read), but I like to think of it as an execution context that contains everything that was in scope at the time a function is called (including all variables). Each time a function is called, such an execution context it created. Since everything in javascript is garbage collected and will only be freed/destroyed when there are no references left to it, this is true for this execution context too (e.g. closure). As long as something has a reference to it or something in it, then the execution context will stay alive and can be used by any code that might run into that execution context.
Line by line annotation:
// first10 is assigned the anonymous function that the call to Range()
// returned. That anonymous function has access to the original arguments
// passed to the Range(1,10) call and other local variables in that function.
var first10 = Range (1,10) ; // no new ..() here, so no instance should be created.. only Range is called..
// same as the call before, except this also includes the step argument
var first10Odd = Range(1,20,2) ; // and Range is called again..
// this makes sense because Range(1,10) returns a function so
// when you alert it's value, it tells you it's a function
alert(first10); // alerts - function(i) { ... }
alert(first10Odd); // alerts- function(i) { ... }
// When you execute the function in first10, it runs that function
// and the alert shows the return value from that function
// This particular function is set to return the entire array if nothing is passed
// to it
alert(first10()) ; // alerts - 1,2,3,...10
alert(first10Odd()); // alerts - 1,3,5,...19
// This particular function is set to return a specific index from the array
// if an argument is passed to it
alert(first10(0)); // alerts - 1
alert(first10Odd(9)); // alerts- 19
If you know how to use the javascript debugger, you can set a breakpoint on this line if (i === undefined) { return getAll() ;} in the inner function and you will be able to inspect all the variables that are in scope, including start, end and step from the outer function.
You may find this article useful reading as it encapsulates some of the ways that closures can be used with object declarations: http://javascript.crockford.com/private.html (not exactly what is being done here, but might help you understand them).
Welcome to javascript closures. Lets take line by line.
var first10 = Range(1,10);
var first10Odd = Range(1,20,2);
We know that Range is just a function. So, in these two lines we are just calling Range function with 2 and 3 arguments respectively.
Now, what happens when you call a function. The obvious answer is, the body of the function gets executed. What do we have in the body of the function.
if (step === undefined ) step = 1;
var arr = [], index = 0;
while(start <= end) {
arr[index] = start ;
index += 1;
start += step;
}
I hope that the above seen lines are pretty obvious and you don't have any problems with them.
var getAll = function () {
return arr;
};
What does this line do? It creates a function at run time. Why runtime? Lets see an example.
<script>
func1();
var func1 = function() {
alert("Hi");
}
</script>
<script>
func1();
function func1() {
alert("Hi");
}
</script>
If you use the first script block, it will throw error. Why? You are calling a function which hasn't been defined yet. The second case, you are defining the function during javascript parsing time itself. The type of function which was created in the first case is called anonymous function. Let us get back to getAll. Now we know that getAll is simply a variable which points to an anonymous function, lets look at what it does. It returns arr. How does it have access to arr? It is declared outside the function and so it still has access to it. Same case with
var getOne = function(n) {
return arr[n] ;
};
Now the very important part,
return function(i) {
if (i === undefined) {
return getAll();
} else {
return getOne(i);
}
};
What does it do? It returns a function. To be precise, it returns an anonymous function. Whenever Range is called, it creates a new anonymous function, which accepts one parameter and returns it. So, now what do first10 and first10Odd have? Yes. You are right, they have functions. I hope that explains
alert(first10); // alerts - function(i) { ... }
alert(first10Odd); // alerts - function(i) { ... }
Let us examine both the functions. When first10 is called with nothing, I mean, first10(), the parameter i takes the value undefined. So, we are actually making a call to the anonymous function with no parameters and it is supposed to return getAll(). If you remember, first10 was created with Range(1,10);. So, the arr will now have [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].
You might ask, when we return from the function, wont the variables declared inside the function go out of scope. The answer is Yes and No. Yes, when you simply return a value. No, when you return a function. When you return a function, the state of the variables will be maintained. This property is called closures. That is why it returns
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] for alert(first10())
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19] for alert(first10Odd())
1 for alert(first10(0))
19 for alert(first10Odd(9))
Please read more about Closure here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures
I've been building a basic live-evaluation javascript development environment (I call it the WEPL.) over the past few days, and realized it'd be nice to be able to associate error messages to line numbers. Unfortunately, eval() doesn't provide a nice way to do this, that I can find.
The solution I've come up with so far is to transform the source before eval() so that it's a set of nested calls to a wrapper to eval() that records some information before eval, checks to see if the eval succeeds, and then uses that info to output more useful troubleshooting information to the user.
My question is, why might this be a bad idea? What problems do I need to solve to make sure this works well?
An example of the sort of transformation I mean, just to make this concrete.
This
if (cond) {
return foo + bar;
}
else {
return baz + quux;
}
becomes this
if (myEval('cond')) {
return myEval("myEval(\"foo\") + myEval(\"bar\")");
else {
return myEval("myEval(\"baz\") + myEval(\"quux\")");
}
Where I obviously didn't wrap the highest level, though I could've, and the programmatic version would.
This won't work if you want to accept even remotely complex scripts. A few potential problems:
Scope
var i = 1; // global scope
!function() {
var i = 2; // function scope
}();
alert(i); // 1
vs.
myEval('var i = 1;'); // global scope
myEval('!function() {
myEval(\'var i = 2;\'); // eval has global scope, always
}();');
myEval('alert(i);'); // 2
Closures
!function() {
var i = 1; // local to outer function
!function() { // inherits context from outer function
alert(i); // 1
}();
}();
vs.
myEval('!function() {
myEval(\'var i = 1;\'); // local to outer function
myEval(\'!function() { // eval has global scope; myEval inherits from wherever it was defined
myEval(\\\'alert(i);\\\'); // undefined
}();\');
}();');
this
var obj = {
n: 1,
f: function() {
return this.n; // this is the object f is called from
}
}
alert(obj.f()); // 1
vs.
myEval('var obj = {
n: myEval(\'1\'),
f: myEval(\'function() {
return myEval(\\\'this.n\\\'); // this is always the window in eval
}')
}');
myEval('alert(obj.f());'); // undefined
Escape creep
You need to escape every quote, and you need to escape escape signs as well. In code with lots of objects, closures, inner functions etc. this will result in escape signs becoming unmanageable:
!function() {
$(function() {
$('#foo').click(function() {
setTimeout(function() {
$.post('/', function(res) {
log(res);
});
}, 1000);
});
});
}();
(note that this is not a particularly contrived or complicated example, it only involves a delyed action with a callback firing on a certain event)
myEval('!function() {
myEval(\'$(myEval(\\\'function() {
myEval(\\\\\\\'$(\\\\\\\'#foo\\\\\\\').click(myEval(\\\\\\\\\\\\\\\'function() {
myEval(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'setTimeout(myEval(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'function() {
myEval(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'$.post('/', myEval(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'function(res) {
myEval(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'log(res);\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\');
}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'));\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\');
}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'), 1000);\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\');
}\\\\\\\\\\\\\\\'));\\\\\\\');
}\\\'));\');
}();');
You can probably see what I am getting at.
I had to do something similar when working on an extension for IE. I ended up creating a global variable called 'lineNumber' and I transformed the code to be more like this:
lineNumber = 1; if (cond) {
lineNumber = 2; return foo + bar;
}
else {
lineNumber = 5; return baz + quux;
}
Of course, I made to make sure I used curly braces around all blocks and had to keep my coding simple enough to avoid confusing my poor lame parser -- but it got me through it.
Can I write a function that returns iteself?
I was reading some description on closures - see Example 6 - where a function was returning a function, so you could call func()(); as valid JavaScript.
So I was wondering could a function return itself in such a way that you could chain it to itself indefinitely like this:
func(arg)(other_arg)()(blah);
Using arguments object, callee or caller?
There are 2-3 ways. One is, as you say, is to use arguments.callee. It might be the only way if you're dealing with an anonymous function that's not stored assigned to a variable somewhere (that you know of):
(function() {
return arguments.callee;
})()()()().... ;
The 2nd is to use the function's name
function namedFunc() {
return namedFunc;
}
namedFunc()()()().... ;
And the last one is to use an anonymous function assigned to a variable, but you have to know the variable, so in that case I see no reason, why you can't just give the function a name, and use the method above
var storedFunc = function() {
return storedFunc;
};
storedFunc()()()().... ;
They're all functionally identical, but callee is the simplest.
Edit: And I agree with SLaks; I can't recommend it either
Yes.
Just return arguments.callee;
However, this is likely to result in very confusing code; I do not recommend it.
You can do what you want as following:
// Do definition and execution at the same time.
var someFunction = (function someFunction() {
// do stuff
return someFunction
})();
console.log(someFunction)
arguments.callee is not supported in JavaScript strict mode.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode
Even sorter that all the above is:
f=()=>f
There is a simple way to achieve this doing the following:
let intArr = [];
function mul(x){
if(!x){
return intArr.reduce((prev, curr) => prev * curr)
}
intArr.push(x);
return mul;
}
console.log(mul(2)(4)(2)()); => outputs 16
It is also possible just to return the argument the self invokable function like
console.log( (function(a) { return a; })(1) ); // returns 1