So, I'm still reading Apress Pro Javascript Techniques and i'm having troubles with closures.
As John Resig states:
Closures allow you to reference variables that exist within the parent function.
However it does not provide the value of the variable at the time it is created; It provides the last value of the variable withing the parent function. The most common issue under which you'll see this occurr during a for loop. There is one variable being used as an interaor (e.g., i). Inside of the for loop, new functions are being created that utilize the closure to reference the iterator again. The rpoblem is tat the time the new closured functions are called, they will reference the last value of the iterator (i.e., the last position in an array), not the value taht you woul expect.
Then he presents, in listing 2-16 an example using anonymous functions to induce scope.
/**
* Listing 2-16. Example of Using Anonymous Functions to induce the
* Scope Needed to Create Multiple Closure-Using Functions
*/
// An element with an ID of main
var obj = document.getElementById("main");
// An array of items to bind to
var items = ["click", "keypress"];
for (var i = 0; i < items.length; i++) {
// Use a self executed anonymous function to induce scope
(function() {
// Remembre the value within this scope
var item = items[i];
// Bind a function to the element
obj["on" + item] = function() {
// item refers to a parent variable that has been successfully
// scoped within the context of this loop
alert("thanks for your " + item);
};
})();
}
This example works as expected, and the behavious of the main object is correct.
The in the following, it uses another time a self-executing function to induce scope, during an iteration.
The purpose of the function is to create an object, defining getters and setters for all its properties. In this case, the example does not work.
/**
* Listing 2-25. Example of Dynamicaaly Generated Methods That Are Created
* When a New Object is instantiated
*/
// Create a new user object that accepts an object of properties
function User(properties) {
// Iterate thorugh the properties of the object, and make sure
// that it's properly scoped (sas discussed previously)
var that = this;
for (var i in properties) {
(function() {
console.log("property: " + i);
// Create a nwe getter for the property
that["get" + i] = function() {
return properties[i];
};
// Create a new setter for the property
that["set" + i] = function(val) {
properties[i] = val;
};
})();
}
}
// Create a new user object instance and pass in an object of
// properties to seed it with
var user = new User({
name: "Bob",
age: 44
});
// Just note that the name property does not exists, as it's private within the
// properties object
alert(user.name == null);
// However, we're able to access its value using the new getnaem()
// method that was dynamically generated
console.log("name: " + user.getname()); // name: 44 :(
alert(user.getname() == "Bob");
// Finally, we can see that it's possible to set and gt the age using
// the newly generated functions
user.setage(22);
alert(user.getage() == 22);
Instead, after passing the i parameter as argument to the self-executing function,it works.
for (var i in properties) {
(function(prop) {
console.log("property: " + i);
// Create a nwe getter for the property
that["get" + prop] = function() {
return properties[prop];
};
// Create a new setter for the property
that["set" + prop] = function(val) {
properties[prop] = val;
};
})(i);
}
My question is:
Why in the first case (for loop), it is not necessary to pass the i parameter, while
in the second (for in) it is needed in order to work properly?
In the first example you are declaring a copy of the contents of the array element in a local variable:
var item = items[i];
As the inline comment says, here we're remembering the value within the closure scope.
In the 2nd example, instead of passing i as a parameter, you could also have done:
(function() {
var prop = i; // See here!
console.log("property: " + i);
// Create a nwe getter for the property
that["get" + prop] = function() {
return properties[prop];
};
// Create a new setter for the property
that["set" + prop] = function(val) {
properties[prop] = val;
};
})();
Which makes both examples more similar.
Similarly, you could also alter the first example to pass i as a parameter, rather than declaring it verbosely in a variable.
(function(item) {
// Bind a function to the element
obj["on" + items[item] = function() {
// item refers to a parent variable that has been successfully
// scoped within the context of this loop
alert("thanks for your " + items[item]);
};
})(i);
It's arbitrary as to whether you declare a local copy of the variable using a var statement, or pass it as a parameter into your self executing function.
Edit:
#Zecc bought up a good point in the comments, which I'd like to explain:
(function (i) {
// using `i` works as expected.
}(i));
Where as:
(function () {
var i = i;
// using `i` doesn't work... i = undefined.
}());
This is because the var variable = value statement is effectively:
(function () {
var i;
i = i;
}());
and the var keyword always assigns the variable(s) following it with the value undefined.
It's because you're referencing i within that.get and that.set in the second case, while in the first case, you're referencing item, which is invariant.
In the first example, the self-executing function has access to the current value that the reference i points to (since it is executed right away), it makes a copy of the current item with item=item[i] so that the inner function for the event handler, which will be called later, will reference the correct item.
If you wouldn't do that the inner function, the event handler, since it doesn't execute right away would reference to the i in the top functions' scope; since the for will be long finished executing when you get to click the thing, it would reference to the last value of i most probably.
By keeping the current item with item=item[i] in the self executing function you get in item the correct current item for each one of them and so the event-handler can have access to the right value, the last value placed in each of the local item vars.
Related
I am using history.js. In the stateObj of the pushState function, I want to add a reference to a function (Car.init(), or Boat.init(). In C++, I believe I could use a function pointer.
Then on window.onpopstate, I want to reference that function and call it. I can read the string (Car.init(), but then how can I call the function? I don't want to use eval.
You probably shouldn't, but if you do want to invoke a function based on a global dotted-path name, that could be accomplished like this:
function callFunction(name, var_args) {
// break the string into individual property/method names
var parts = name.split('.');
// start with a reference to the global object
var target = window;
var previousTarget = null;
for (var i = 0; i < parts.length; i++) {
// keep a copy of the previous reference to use as the `this` value
previousTarget = target;
// change the reference to the next named property
target = target[parts[i]];
}
// grab the remaining arguments
var args = Array.prototype.slice.call(arguments, 1);
// call the target function, with previousTarget as the subject, using args
return target.apply(previousTarget, args);
}
// This is in the top-level/global scope. This won't work for a local definition.
var MyApp = {
currentUser: {
name: 'Joe',
displayName: function(greeting) {
alert(greeting + " ," + this.name + "!");
}
},
openBar: function() {
alert("The Foo Bar is now open for business!");
}
};
var functionName = 'MyApp.currentUser.displayName';
callFunction(functionName, "Hello");
This is safer than using eval (good call on avoiding it), but is still pretty wacky and very difficult for JavaScript interpreters to optimize. Instead, the recommended approach is to use a reference (pointer) to the function. This is probably similar to what you'd do in C++. If the function doesn't use this (i.e. if it's a static function, not a method), you can just take a reference to the function directly.
var open = MyApp.openBar;
open();
If it does have a this value, you'll need to use the .bind() method to preserve its association with the object it's attached to.
var display = MyApp.currentUser.displayName.bind(MyApp.currentUser);
display("Greetings");
If you pass additional arguments to .bind(), you can also specify the leading arguments that will be used to call the function.
var displayHello = MyApp.currentUser.displayName.bind(MyApp.currentUser, "Hello");
displayHello();
Thanks to this question I understand how a function may take two sets of parentheses and how a function may return another function which fires immediately after being returned.
What I do not understand is why this is good to know? How could this be applied to solve a problem?
The example of:
function add(x){
return function(y){
return x + y;
};
}
add(3)(4) === 7; // true
Works fine - sure. But why not just write it like this instead?
function add(a, b) {
return a + b;
}
add(3, 4) === 7; // true
Lets take the same code which you have mentioned.
function add(x) {
return function(y) {
return x + y;
};
}
var adder3 = add(3); //Forming adder3
var op1 = adder3(4) // 7
var op1 = adder3(5) // 9
// Now adder 10:
var adder10 = add(10); //Forming adder3
var op1 = adder10(4) // 14
var op1 = adder10(5) // 15;
Hope you understand!!
Revert me if you need more info on closure.
Your example called as closures
Closures’ Rules and Side Effects
Closures have access to the outer function’s variable even after the outer function returns:
One of the most important and ticklish features with closures is that the inner function still has access to the outer function’s variables even after the outer function has returned. Yep, you read that correctly. When functions in JavaScript execute, they use the same scope chain that was in effect when they were created. This means that even after the outer function has returned, the inner function still has access to the outer function’s variables. Therefore, you can call the inner function later in your program. This example demonstrates:
function celebrityName(firstName) {
var nameIntro = "This celebrity is ";
// this inner function has access to the outer function's variables, including the parameter
function lastName(theLastName) {
return nameIntro + firstName + " " + theLastName;
}
return lastName;
}
var mjName = celebrityName("Michael"); // At this juncture, the celebrityName outer function has returned.
// The closure (lastName) is called here after the outer function has returned above
// Yet, the closure still has access to the outer function's variables and parameter
mjName("Jackson"); // This celebrity is Michael Jackson
Closures store references to the outer function’s variables; they do not store the actual value.
Closures get more interesting when the value of the outer function’s variable changes before the closure is called. And this powerful feature can be harnessed in creative ways, such as this private variables example first demonstrated by Douglas Crockford:
function celebrityID() {
var celebrityID = 999;
// We are returning an object with some inner functions
// All the inner functions have access to the outer function's variables
return {
getID: function() {
// This inner function will return the UPDATED celebrityID variable
// It will return the current value of celebrityID, even after the changeTheID function changes it
return celebrityID;
},
setID: function(theNewID) {
// This inner function will change the outer function's variable anytime
celebrityID = theNewID;
}
}
}
var mjID = celebrityID(); // At this juncture, the celebrityID outer function has returned.
mjID.getID(); // 999
mjID.setID(567); // Changes the outer function's variable
mjID.getID(); // 567: It returns the updated celebrityId variable
Reference site : http://javascriptissexy.com/understand-javascript-closures-with-ease/
Functions which return functions are useful when you want similar functions which depend on some parameters.
A real life example: [].sort can be called with a custom comparator function, but it can make sense to define a comparator function to allow more customizations:
function comparator(options) { // Function which returns a function
return function(a, b, tmp) {
if(options.reverse) tmp = a, a = b, b = tmp;
if(options.map) a = options.map(a), b = options.map(b);
if(options.func) return options.func(a, b);
return a < b ? -1 : (b < a ? 1 : 0);
}
}
Then you can use
[1,11,10,2].sort(comparator({map: String})); // [1, 10, 11, 2]
[1,11,10,2].sort(comparator({reverse: true})); // [11, 10, 2, 1]
[1,11,10,2].sort(comparator({func: Function.prototype})); // [1, 11, 10, 2]
if we require a function in certain state with certain value then we can use it inside another function and return that, so that the return function with certain state can be directly used in different scenario.
you can check out various example on closure.
http://javascriptissexy.com/understand-javascript-closures-with-ease/
If you know the first param is always going to be the same, then it will convenient to have it closure, instead of passing it again and again. For simple programs, it may not make sense. But, for programs which handles repetitive params more often, this technique definitely comes handy.
Other than closures you can also use it for pre-processing as a one time job, consider if you had to do something intensive, e.g. generate a million things;
function generateSessionSecrets(lock) {
var secrets = [], i = 1000000;
while (i-- > 0) {
secrets[i] = Math.random();
}
return function(key, i) {
if (key === lock) return secrets[i];
}
}
var chest = generateSessionSecrets('fizz');
chest('fizz', 0); // e.g. 0.2096199430525303
chest('fizz', 1); // e.g. 0.30329699837602675
// ...
chest('fizz', 0); // still 0.2096199430525303
(This is an example of concept, not an example of real security)
there isn't a point to using it immediately. you would use it to create a function to attach it to an event or use as a callback for an asynchronous function. an example might be such:
function factory(param){
return function(result) {
if (result==param) dosomething();
}
}
$('#domobject').click({
param = $('#domvalue').value;
asynch_function(factory(param));
});
Here I've attached a click event to presumably a button. When it is clicked it will retrieve the value of an input and create a function based on it and call an asynchronous function with the newly created function as it's callback. The asynchronous function might be an ajax request. When the asynchronous function completes the function that factory created, the callback, will be called. It will check the return value the asynchronous function passed to the callback against the param specified when the event was attached.
If we move the dom lookup to inside the callback function, then we wouldn't need factory or param, but then it would use the value that is in the input at the time when the asynch function has returned, rather than when the button was clicked which is later and the value might have changed.
Sometimes, you won't be able to obtain a value you need in the context of the callback for other reasons. Or it might just be that you want to abstract out a class of functions so you don't have to retype a slightly different version of it in all the places you use it.
In a typical js class, all calls to member functions must be preceded by this. I was looking at a technique that would let me create a library of inter-dependent STATIC functions and relying on closure/scope to make things a bit easier.
Example:
var Singleton={
//main entry point
// call with fn name, args...
call:function(){
var args=[];
if (arguments.length==0) {
return;
}
// get the fn name
var fn=arguments[0];
var x;
// make args array
for (x=1;x<arguments.length;x++) {
args[args.length]=arguments[x];
}
// I want to get rid of this part
// See below for what I wish
// Here I have access to fns below due to hoisting in js
// so I put them in a map...
var fns={
test:test
// etc, more like this I do not want to type/maintain
}
// ... all so I can do this
// get my function.
var fun=fns[fn];
// instead of that, I would like to "override whitespace" and
// say something like:
// var fun=['fn_name'];
// so I can index into local scope and get a fn
//
// log error if not found
if (typeof fun=='undefined') {
loge('Singleton: function not found:'+fn);
return;
}
// ok, run the function
return fun.apply(window,args);
// the test fn accesses test2() without dot notation
function test(a){
// Note: here in test fn it can access test2()
// without using this.test2() syntax
// as you would in normal objects
var s=test2();
alert(s+' test:'+a);
};
function test2(){
return 'test2';
};
}
}
I was hoping someone more familiar with advances in javascript might have advice on how to emulate an "implied but unnecessary this", it always struck me as strange that this defaults to window, and wouldn't it be nice if this could be pointed to an anonymous object with the local scope attached.
I would love to say ['localObject'] to get something in scope.
Edit:
After seeing some of the responses, I will restate this in the form of a challenge:
What I am looking for is a syntax cheat, a way to, as #Varuna put it, "1. Access static methods without using this variable i.e. they will remain global to one another. 2. Do not want to maintain a local array for static methods and want to achieve with in the local scope itself."
Put differently, I need to have the declared functions Register themselves, but I don't want to state the function name more than once. I suppose #Varuna has a solution using eval to access the local scope.
The following approach wont work:
var o={};
o['fn']=function fn(){};
o['fn2']=function fn2(){};
...because you have to state the fn name twice, but closure is preserved.
And this:
var a=[
function fn(){}
,function fn2(){}
];
Register(a);
Will not work because, AFAIK, you lose closure, ie. fn2 cannot see fn. Which also makes the following declarative style a "this nightmare":
window.MINE={
fn:function fn(){
//this?
// want to say fn2(), not this.fn2(), nor MINE.fn2()
}
,fn2:function fn2(){
//this?
}
,deeper:{
//more
}
};
But something like this might work, if you created a weird property that does the registration on assignment:
var registar=new Registar();
registar.reg=function fn(){};
registar.reg=function fn2(){};
//then access
var fn=registar.getFn(n);
// or
var fn=registar._[n];
The above relies on js properties and having access to fn.name, which is not available in all cases AFAIK.
If I understand correctly, you want to create objects that:
have static members
... which can be accessed without using the this notation
The easiest solution (assuming I've properly understood your query), would be to simply use a closure to store your stratic fields, access them directly by name, then explicitly add them as object members.
Consider:
var myConstructor = (function(){
var foo = 'someStaticField';
var bar = function(){
alert('A static method returns ' + foo);
};
return function(){
return {
foo : foo,
bar : bar
};
};
})();
var myInstance = new myConstructor();
As per my understanding, you want to:
1. Access static methods without using this variable i.e. they will remain global to one another.
2. Do not want to maintain a local array for static methods and want to achieve with in the local scope itself.
You can check whether a method exist using eval.Check Here
Only drawback is that this will be using eval method.
Code will be:
var Singleton = {
//main entry point
// call with fn name, args...
call: function () {
var args = [];
if (arguments.length == 0) {
return;
}
// get the fn name
var fn = arguments[0];
var x;
// make args array
for (x = 1; x < arguments.length; x++) {
args[args.length] = arguments[x];
}
//check whether function exist in local scope and not in global scope
if (typeof eval(fn) !== 'undefined' && typeof window[fn] === 'undefined') {
// ok, run the function
return eval(fn).apply(window, args);
}
else{
// log error if not found
loge('Singleton: function not found:' + fn);
return;
}
// the test fn accesses test2() without dot notation
function test(a) {
// Note: here in test fn it can access test2()
// without using this.test2() syntax
// as you would in normal objects
var s = test2();
alert(s + ' test:' + a);
};
function test2() {
return 'test2';
};
}
}
How about declaring functions that can access each other in separate closure, and exporting them to main method by binding your call method to an object containing the functions? Something like previous post (modified slightly):
var Singleton = {
call: (function() {
// here 'call' is bound to object containig your test functions
// this: {test, test2}
if (0 == arguments.length) return;
// log error if not found
if ('function' != typeof this[arguments[0]]) {
console.warn('Singleton: function not found:' + arguments[0]);
return;
}
// '...index into local scope and get function
// ie. get the function by it's name
return this[arguments[0]].
apply(window, Array.prototype.slice.call(arguments, 1));
// --- or:
// you can explicitly introduce function names to current scope,
// by `eval`-ing them here (not very much preferred way in JavaScript world):
for (var fname in this)
if (this.hasOwnProperty(fname))
eval('var ' + fname + ' = ' + this[fname]);
// and you can reference them directly by using their names
var fn = eval(arguments[0]);
return fn.apply(window, Array.prototype.slice.call(arguments, 1));
}).bind(
(function() {
var _exports = {};
function test (a) {
var s = test2();
alert(s + ' test: ' + a);
}
function test2 () {
return 'test2';
}
_exports['test'] = test;
_exports['test2'] = test2;
return _exports;
})()
)};
Singleton.call('test', 'foo and stuff');
//
previous post:
You are talking about Function#bind functionality that enables 'customizing' function's context. .bind() your call method to required 'local context' like this:
var Singleton = {
//main entry point
// call with fn name, args...
call: (function() {
// here `this` (context) is object bound to `call` method
// not `global` object, which is default for 'unbound' functions
var locals = this; // {fns, shift, loge, isfunc}
var fn;
var fun;
var x;
if (arguments.length == 0)
return;
// get the fn name
fn = locals.shift(arguments);
// '...index into local scope and get a fn'
fun = locals.fns[fn];
// log error if not found
if (!locals.isfunc(fun)) {
locals.loge('Singleton: function not found:' + fn);
return;
}
// ok, run the function
return fun.apply(window, arguments);
// lock `call`'s context to provided object
// and use `this` to reference it inside `call`
}).bind({
fns: (function(_) {
// and you can '...create a library of inter-dependent STATIC functions'
// in this closure and invoke them in `call` method above
_.test = function (a) {
var s = _.test2();
alert(s + ' test: ' + a);
};
_.test2 = function() {
return 'test2';
};
return _;
})({}),
// and create couple of helper methods as well...
isfunc: (function(_getclass) {
_getclass.func = _getclass(_getclass);
return ('function' !== typeof(/foo/)) ?
function(node) {
return 'function' == typeof node;
} :
function(node) {
return _getclass.func === _getclass(node);
};
})(Function.prototype.call.bind(Object.prototype.toString)),
loge: console.warn,
shift: Function.prototype.call.bind(Array.prototype.shift)
}),
};
Singleton.call('test', 'foo and stuff');
// eof
Here's one 'in your face answer', because I really don't like what I see here.
I don't see why you need this kind of construct, you already have that as part of language core.
1. dynamic lookup
you are doing it in a rather 'unprecedented' kind of way,
hashes already do that for you, and it's lightning fast to do a hash search.
If you are eval()-ing random strings to do simple name lookup you really have to
step aside from a keybord for a while... (no offense please)
2. closures
you are saying about 'using closures' which you actualy don't use.
your call function redeclares test functions each time it gets called,
and looks the ('fresh version') functions in it's own variable scope table,
instead of lookig them up in parent scope chains (aka. closures)
outside it's lexical location
3. nfe vs. nfd
ie. named function expressions vs. named function declarations
...you cannot assign a function to a local var and have it retain closure.
It is a feature, you might not be aware of how it works (it tripped me up as well).
check this article out for clarification
4. exceptions
Singleton: function name not found... x4!
Just go ahead and call a function,
interpreter will throw for you anyway if it cannot find/execute
5. eval (aka. ^^)
Singleton.call.ctx.fun = eval(Singleton.call.ctx.fn);
eval takes any string here(#!), and gladly executes ones like:
'for(;;);', or 'while(1);'... forever.
You probably don't want to have any code running unless it was your stuff.
6. arguments handling
It is considered best practice out there to use single (Object) options parameter
to 'fine tune' any significant piece of bundled functionality,
instead of trying to figure that out by type checking provided argument list
Here's, in couple of simple lines, what I (and as I can see #Jimmy Breck-McKye) suggest you should do:
var Singleton.call = (function () {
var funcmap = {
'f_1': function () {},
// etc.
'f_N': function () {},
};
return function (options) {
// options members:
// context, (Object) context, (defaults to global if none is given)
// func, (String) function_name,
// args, (Array) arguments to pass into a function
// this line does everything your 100+ lines long snippet was trying to:
// look's up parent scope for a function, tries to run it
// passing provided data, throws if it gets stuck.
return funcmap[options.func].apply(options.context, options.args);
};
})();
//
Answering my own question here.
The core of the issue is that you cannot assign a function to a local var and have it retain closure.
Consider that when writing a function with global and window scope, this is not necessary to call another function with identical scope. Such is not the case with member functions.
Another way of saying this is that there is no space where your cursor can sit and as you declare a function it automatically gets attached to the current this.
function fn(){}// if we are in global scope, then window.fn becomes defined
// but if we are inside, say, a constructor, simple declaration will not attach
// it to this, but fn is available in scope.
Any assignment on function declaration BREAKS part of the expected closure:
var IdentifierAvailableToClosure=function Unavailable(){}
But assignment after declaration works:
function NowAvailable(){}
var SynonymAvailableToo=NowAvailable;
This is what I meant by not wanting to repeat the name twice to get the mechanism to work.
This fact made me abandon other methods and rely on eval as suggested. Here is a first draft:
// This object is an encapsulation mechanism for a group of
// inter-dependent, static-ish, functions that can call each other
// without a this pointer prefix.
// Calls take the form of:
// Singleton.call(functionName:String [,arg1]...)
// or
// Singleton.call(contextObject:Object, functionName:String [,arg1]...)
// If a context is not provided, window is used.
//
// This type of mechanism is useful when you have defined a group
// of functions in the window/global scope and they are not ready
// to be formalized into a set of classes, or you have no intention
// of doing that
//
// To illustrate the issue, consider that a function
// which is defined in window/global scope
// does not have to use the this pointer to call a function of
// identical scope -- yet in a class member function, the this pointer
// MUST be used
// Therefore, trying to package such functions requires injecting
// the this pointer into function bodies where calls to associater
// functions are made
//
// Usage is primarily for development where one has control over
// global namespace pollution and the mechanism is useful in
// refactoring prior to formalization of methods into classes
var Singleton={
// Main call point
call:function(){
// Bail with error if no args
if (arguments.length==0) {
throw('Singleton: need at least 1 arg');
}
// As all functions in the local scope library below
// have access to the local scope via closure, we want to reduce
// pollution here, so lets attach locals to this call
// function instead of declaring locals
//
// Prepare to call anon fn
Singleton.call.args=arguments;
// Make ctx have args, context object, and function name
Singleton.call.ctx=(function (){// return args,ctx,name
// out
var args=[];
//locals
var x, fn;
// collapse identifier
var a=Singleton.call.args;
// closure object avail to functions, default to window
that=window;
// first real function argument
var arg_start=1;
// first arg must be function name or object
if (typeof a[0]=='string') {// use window ctx
fn=a[0];
// if first arg is object, second is name
}else if (typeof a[0]=='object') {
// assign given context
that=a[0];
// check second arg for string, function name
if (typeof a[1]!='string') {
var err='Singleton: second argument needs to be a fn name'
+' when first arg is a context object';
throw(err)
return;
}
// ok, have a name
fn=a[1];
// args follow
arg_start=2;
}else{
// improper arg types
var err='Singleton: first argument needs to be a string or object';
throw(err)
}
// build args array for function
for (x=arg_start;x<a.length;x++) {
args[args.length]=a[x];
}
// return context
return {
args: args
,that:that
,fn:fn
};
})();
// using function library present in local scope, try to find specified function
try{
Singleton.call.ctx.fun=eval(Singleton.call.ctx.fn);
}catch (e){
console.error('Singleton: function name not found:' + Singleton.call.ctx.fn);
throw('Singleton: function name not found:' + Singleton.call.ctx.fn);
}
// it must be a function
if (typeof Singleton.call.ctx.fun !== 'function') {
console.error('Singleton: function name not found:' + Singleton.call.ctx.fn);
throw('Singleton: function name not found:' + Singleton.call.ctx.fn);
}
// library functions use that instead of this
// that is visible to them due to closure
var that=Singleton.call.ctx.that;
// Do the call!
return Singleton.call.ctx.fun.apply(that, Singleton.call.ctx.args);
//
// cool library of functions below,
// functions see each other through closure and not through this.fn
function test(s){
alert(test2()+' test:'+s);
}
function info_props(){
console.info(this_props());
}
function test2(){
return 'test2';
}
function this_props(){
var s='';
for (var i in that) {
s+=' '+i;
}
return s;
};
}
};
I am reading Stoyan Stefanov's "Javascript Patterns". I am confused on the private static member section -- how does it works underlying.
var Gadget = (function () {
var counter = 0;
return function () {
console.log(counter += 1);
};
}());
var g1 = new Gadget(); // logs 1
var g2 = new Gadget(); // logs 2
Why "counter" becomes a static member?
Many thanks in advance!
Gadget is a closure over counter. Whenever you call Gadget, 1 is added to counter.
It might be easier to see if you write the code as
var counter = 0;
var Gadget = function () {
console.log(counter += 1);
};
var g1 = new Gadget(); // logs 1
var g2 = new Gadget(); // logs 2
instead. It should be clear that there is only one counter variable and that its value is increased whenever Gadget is called.
The difference in your code is that it is wrapped in an IIFE, so that counter is not accessible from any other function other than the one returned from the IIFE (which is assigned to Gadget), thus making counter "private".
See also: What is the (function() { } )() construct in JavaScript?
It becomes a static member, because it is not modified outside of the object. It isn't dynamic.
So, it becomes a static member.
In other words, all variables which are used inside an object, and which are not functions and properties, and which is used for internal logic is called static member.
The reason is because the closure for the function returned by the immediate function includes a reference to the same counter for all instances of Gadgets. Things happen like this (roughly):
The immediate function is immediately called (duh).
The function returned will have a reference to 'counter'.
When you call 'new Gadget()' an instance of Gadget is returned.
a. This instance of Gadget is just another way of calling the function that gives an empty object for the 'this' and returns it as well. So g1 and g2 are blank objects.
b. This means all instances will have a reference to 'counter'.
It's private, because nothing outside the object that is created by the immediate execution of the anonymous function whose definition starts on line 1 can access the variable counter.
It's not really static, because, if Gadget is defined in an inner scope, the storage used for Counter could be garbage-collected once Gadget and all of the Gadget objects that it has created have been discarded. But it behaves like static for most purposes when used at the top level.
Confusingly, this code in the more complete example that follows does not do what Stefanov says.
var Gadget = (function () {
var counter = 0, NewGadget;
NewGadget = function () {
counter += 1;
};
NewGadget.prototype.getLastId = function () {
return counter;
};
return NewGadget;
}()); // execute immediately
var iphone = new Gadget();
iphone.getLastId(); // 1
var ipod = new Gadget();
ipod.getLastId(); // 2
var ipad = new Gadget();
ipad.getLastId(); // 3
He writes: "Because we’re incrementing the counter with one for every object, this static property becomes an ID that uniquely identifies each object created with the Gadget constructor.". That's just wrong. There is only one counter, and all of the Gadget objects have a reference to it. The function getLastId() does just what its name suggests: gets the most recently issued id, and not the value of counter when the gadget was created.
So, the above example runs, and produces the results indicated by the comments. But if you try
iphone.getLastId(); // 3
one more time, you get 3 — the current value of counter, not the value when iPhone was created.
To get the effect of each Gadget having a unique id, we can use a fresh variable for each Gadget, like this:
var Gadget = (function () {
var counter = 0, NewGadget;
NewGadget = function () {
counter += 1;
var myId = counter;
this.myUid = function () {
return myId;
};
};
return NewGadget;
}()); // execute immediately
var iphone = new Gadget();
iphone.myUid(); // 1
var ipod = new Gadget();
ipod.myUid(); // 2
var ipad = new Gadget();
ipad.myUid(); // 3
iphone.myUid(); // 1
Note that myId is definitely not static, even though we are using the same pattern as for counter. However, it is private. There is a separate myId for each Gadget, and it's not a property of the Gadget object — it's truly hidden. But the object's myUid function has closed over it.
Is there any way to break a closure easily in JavaScript? The closest I have gotten is this:
var src = 3;
function foo () {
return function () {
return src; }
}
function bar (func) {
var src = 9;
return eval('('+func.toString()+')')(); // This line
}
alert(bar(foo()));
This prints '9', instead of '3', as a closure would dictate. However, this approach seems kind of ugly to me, are there any better ways?
Your code is not breaking the closure, you're just taking the code the makes up a function and evaluating it in a different context (where the identifier src has a different value). It has nothing at all to do with the closure that you've created over the original src.
It is impossible to inspect data that has been captured in a closure. In a sense, such data are even more "private" than private members in Java, C++, C# etc where you can always use reflection or pointer magic to access them anyway.
This could be useful if you are trying to create multiple similar methods in a loop. For example, if you're creating a click handler in a loop that relies on a loop variable to do something a little different in each handler. (I've removed the "eval" because it is unnecessary, and should generally never be used).
// Assign initial value
var src = 3;
// This is the regular js closure. Variables are saved by reference. So, changing the later will
// change the internal value.
var byref = function() {
return src;
}
// To "break" the closure or freeze the external value the external function is create and executed
// immidiatly. It is used like a constructor function which freezes the value of "src".
var byval = function(s) {
return function() { return s };
}(src);
src = 9;
alert("byref: " + byref()); // output: 9
alert("byval: " + byval()); // output: 3
As others said this doesn't seem to be the right thing to do. You should explain why you want this and what you want to achieve.
Anyway, one possible approach could be to access properties of an object inside your function. Example:
var src = 3;
function foo (context) {
context = context || window; // Fall back to the global namespace as default context
return function () {
return context.src;
}
}
function bar (func) {
var context = {src: 9};
return func(context);
}
alert(bar(foo));
If you want to access a variable in a wider scope, just don't reuse the variable name in a narrower scope.
That's how it is supposed to work. Work with it instead of trying to fight it.
Here is the code see if you can understand , closures defined within a loop .
var clicked = false;
for(var i=0;i<temp.length;i++){
(function(index){
if(clicked) return false;
$(temp[index]).on('click',function(){
if($(temp[index]).text()=="" && !$(".cell1").val()){
$(this).text(player1Val);
$(".cell1").val(true);
console.log("first player clicked ");
clicked = true;
$(this).off();
for(var j=0;j<temp.length;j++){
$(temp[j]).off('click');
}
return false;
}
else return false;
});
})(i);
}