Ok, I don't know how to actually ask this question without showing it. (Also explains why I can't figure out how to search for it on Google.)
Given the following like of code:
dijit.byId('leftNavigationPane').onLoad = function(){setSecondaryNav(url.secondaryNavId);};
I want the variable url.secondaryNavId to be evaluated, so what I really want is it to be treated something like this:
dijit.byId('leftNavigationPane').onLoad = function(){ setSecondaryNav('item1'); };
I am sure there is probably a better way to do this, so feel free to suggest something.
Don't use eval!
You can use a self-invoking function and closures as follows:
dijit.byId('leftNavigationPane').onLoad = function(id){
return function(){ setSecondaryNav(id); };
}(url.secondaryNavId);
This will execute the outer anonymous function immediately (at runtime), passing the url.secondaryNavId parameter, which will then create a closure that the inner anonymous function will use (so id will always contain the assignment-time value of the url.secondaryNavId property).
There is the JavaScript eval() function.
Related
I am looking at code that appears to be declaring a function that would need to be called to run. This function is being declared within an anonymous function. Doesn't this mean that the function will be inaccessible to anything outside of this block?
(function () {
var _d = vjo.dsf.EventDispatcher;
var _r = vjo.Registry;
function $1(p0) {
return function (event) {
return this.onSubmit(p0, event);
};
};
})();
Why would someone do this?
I am not sure of the purpose/relevance of $ in this code.
"Doesn't this mean that the function will be inaccessible to anything outside of this block?"
Yes it does.
"Why would someone do this?"
Usually because it contains code for internal use only, though in your example, the function is never invoked.
"I am not of the purpose/relevance of "$" in this code."
No relevance. Just another valid variable character.
The example you posted shows a common pattern of writing "modules" in javascript, although one that has an error. $1 is never invoked and is private, which means it might as well not exist. However, in a valid example, there would be additional code that would call $1 and possibly other functions. Then, when this code was included, the whole thing would evaluate, yet the global namespace would not get polluted with the declarations.
i am new to front-end developing,and now i am reading a lot of js code written by other in my company and find they will use this syntax to store the arguments :
function func1(argu1,argu2){
this.argu1 = argu1;
this.argu2 = argu2;
// other code run here....
}
for me i usually skip this and use the argument directly in my code or get a variable for the n,like this:
function func2(argu1,argu2){
alert(argu1);
alert(argu2);
var arguOne = argu1,arguSec = argu2;
// other code run here...
}
so i want want to ask why use this syntax to store an arguments?
is this a good practice ?and why?
Have i ever miss some concepts that i should know?
see the fiddle, written by the my co-worker who has been no longer a front-ender....
In your first example, func1 can be used to create objects. It is effectively a class definition (constructor). It can be used as follows:
function func1(argu1,argu2)
{
this.argu1 = argu1;
this.argu2 = argu2;
}
var instance = new func1('a', 'b');
alert(instance.argu1);
alert(instance.argu2);
Lordy lord: Instead of defining the function, and calling it at the end, try using a closure. Just keep the function definition as is, but put it in brackets:
(function new_slider (arguments)
{
//your code here
})('#new_slider',1500,150,10);
This way, the function is declared, and invoked at the same time, all functions defined within the main new_slider function will have access to the arguments. There is absolutely no reason to use this.argu1 to store these values. If anything, it creates global variables, which is considered bad practice.
Please google closures in JavaScript, they're extremely powerful
I am attempting to declare a function outside of anonymous function but still have acess to all of the anonymous functions variables
Below is demonstrating what I'm talking about.
I just need to get rid of eval.
//Used to determine where the variable is being stored
var variableScope = "global";
(function(window){
var variableScope = 'insideFunction',
appearingToBeGlobalFunction = function(){
alert("This Function appears Global but really isn't");
};
window["addFunction"]=function(funName,fun){
//window[funName] = fun; Doesn't work
eval("window[funName]="+fun+";");
}
})(window);
addFunction("alertTest",function(){
alert(variableScope);
appearingToBeGlobalFunction();
});
//should alert "insideFunction" and "This Function appears Global but really isn't"
alertTest();
Edit: The goal of this question was to ultimately keep the global scope clean from tons of variables, but still have the convenience of accessing, set and calling as if they were global. I have concluded there is a way to doing what I'm after but it requires a deprecated functionality in javascript.
Here is some example code showing how to accomplish the above without eval.
This article discusses how to use "with".
var variableScope = "global";
var customScope = {
variableScope : 'insideFunction',
appearingToBeGlobalFunction : function(){
alert("This Function appears Global but really isn't");
}
};
function alertTest(){
with(customScope){
alert(variableScope);
appearingToBeGlobalFunction();
}
};
//should alert "insideFunction" and "This Function appears Global but really isn't"
alertTest();
You can't get rid of eval and still expect it to work. That's the only way to take a look at members of the scope after it's been "closed." I've messed around with something similar in the past, but I would never actually use it anywhere. Consider an alternate solution to whatever you're trying to accomplish.
eval("window[funName]="+fun+";");
Oh dear Lord.
The reason this “works” is that you are converting the function fun (alertTest) into a string to put it in the eval argument.
It happens that in most desktop browsers, a native JS function's toString() result will be a string that looks like a function expression containing the same code as the original declaration. You're turning a function back into a string and re-parsing that string in the context of the new enclosing function, so the new function value is the same code but with a different closure.
However, it is not required that Function#toString work like this, and in some cases it won't. It is not safe to rely on function decomposition; avoid.
You can certainly only do this kind of horrific hackery using eval, although there is no reason the window[funName]= part has to be inside the eval. window[funName]= eval('('+fun+')'); would work equally well (badly).
I am attempting to declare a function outside of anonymous function but still have acess to all of the anonymous functions variables
Whyever would you do something crazy like that?
you could force the variables to be in the global scope eg instead of var variableScope = 'insideFunction' you use window.variableScope = 'insideFunction'
The goal of this question was to ultimately keep the global scope clean from tons of variables, but still have the convenience of accessing, set and calling as if they were global. I have concluded there is a way to doing what I'm after but it requires a deprecated functionality in javascript.
Here is some example code showing how to accomplish the above without eval.
This article discusses how to use "with".
var variableScope = "global";
var customScope = {
variableScope : 'insideFunction',
appearingToBeGlobalFunction : function(){
alert("This Function appears Global but really isn't");
}
};
function alertTest(){
with(customScope){
alert(variableScope);
appearingToBeGlobalFunction();
}
};
//should alert "insideFunction" and "This Function appears Global but really isn't"
alertTest();
I was just curious if I could pass a function as a variable. For example:
I have a function
$('#validate').makeFloat({x:671,y:70,limitY:700});
I would like to do something like this:
$('#validate').makeFloat({x:function(){ return $("#tabs").offset().left+$("#tabs").width();},y:70,limitY:700});
This does not work, but ideally every time the variable was accessed it would compute the new value. So if the window was resized it would automatically adjust as opposed to a variable passed in being static. I realize I can implement this directly inside the function\widget, but I was wondering if there was some way to do something like the above.
The concept of this is independent of the plugin. I am talking about the function being "cast" as a variable.
Yes, you can pass an object which will invoke some function when its property is read (this is called a getter), but it is not cross-browser compatible. For example, this will (probably) work in IE9:
var o = {y:70, limitY:700};
Object.defineProperty(o, 'x', {get: function() {return 671;}});
$('#validate').makeFloat(o);
There are other syntaxes for other browsers such as __defineGetter__ for Firefox, and some browsers don't have this functionality at all. So it is practically useless unless you can fully control the environment where your code runs.
This won't work unless x is invoked (obj.x(), instead of just obj.x).
To make it work, the makeFloat() code must check the type of x, and if it's a function, invoke it.
I see what you're trying to do, but it won't work. Why? makeFloat expects the value to be non-function type. It probably uses that value directly. To actually execute the function, makeFloat needs to do x() or even x.call(...) or x.apply(...), which it most certainly isn't doing.
To answer your other question i.e., can you pass functions as variables, the answer is yes. In fact, this is the way callbacks and closures are handled in Javascript. For example, in jQuery when you bind an event handler you are passing in a function as a parameter:
jQuery("#myInputId").click(function() {
...
...
});
Another way that parameters are passed in are as object attributes, for example in jQuery.ajax:
jQuery.ajax({
...
success: function(data) {
},
...
});
In both cases, click and ajax both understand and expect the parameter to be a function and not just a regular variable. For example, assuming you had an object that maintained a list of integers and you had a method called addElement(int), which expected an int parameter, you wouldn't pass in a String. It works the same way in Javascript, except for the fact that the language is not strongly typed. This is why you don't really get a type-mismatch error unless the function explicitly checks the type and throws an exception. This is generally a good practice in such language; I try to do this in the Javascript code that I write.
I've done this with string variables. You'll need to exploit the toString function.
function RefString(fn) { this.toString = function() { return String(fn()); }; }
You can use it like so:
$("#someDiv").somePlugin({optionValue: new RefString(MyFunc), ... });
function MyFunc() {
return new Date().getYear().toString();
}
It works by setting optionValue to a new OBJECT, not necessarily a function. Then anything that reads this object will ask for a value, which by default is the result of the toString function. We simply override the default behavior by executing a function that is specified when the object is constructed.
I'm not sure how it will work for EVERY plugin, but it works when a string or number is expected.
How do you mean "doesn't work"?
It looks like it should compile and run. But what happens is it executes the function and sets the value no different than if you used a constant, or called a function that wasn't inline.
What you need to do is put this line of code in an event that fires when the window is re-sized.
It looks like makeFloat is from a jQuery plugin - are you sure that the plugin is aware that 'x' can be a function and will execute it properly? From the jQuery site, it looks like it only is able to comprehend a number value or 'current' as a string, not a function.
You can pass functions as variables, yes - but that's not actually what you're asking.
What it looks like your asking is "can I set a DOM property to the result of an expression?" to which the answer is "no". (Note - not outside of browser-specific behavior such as IE's CSS Expressions - which have been deprecated in IE8 anyway)
You'll need to bind an event handler to window.onresize and use a function to update the sizing yourself.
In order for a function to be executed from a variable, it has to be called, like so:
$.option.callback.call();
Where option is the containing variable, callback is the function and call executes the function.
It's not like you don't have options though. You can set it up so that the returned value of that function is executed from the line itself. Or you can set it up in the alternative manner that you described.
You need to invoke that function so that it returns the actual value you're looking for. So you're not actually passing in a function, you're invoking it and it's immediately returning a value. For example:
$('#validate').makeFloat({
x:function(){
return $("#tabs").offset().left+$("#tabs").width();
}(),
y:70,
limitY:700
});
Notice the extra () after the function call. This invokes the function immediately, thus returning the value you're looking for.
Note that x doesn't "compute new value" when is accessed (read), but when the function is called, i.e. x(). As Chad mentioned, this is how you can automatically execute a function when windows is resized:
$(window).resize(function() {
// do something
});
[Update] After re-reading your question, I think you may be thinking overcomplicated – isn't this what you are looking for?
$('#validate').makeFloat({
x: $("#tabs").offset().left + $("#tabs").width(),
y: 70,
limitY: 700
});
(function()
{
//codehere
}
)();
What is special about this kind of syntax?
What does ()(); imply?
The creates an anonymous function, closure and all, and the final () tells it to execute itself.
It is basically the same as:
function name (){...}
name();
So basically there is nothing special about this code, it just a 'shortcut' to creating a method and invoking it without having to name it.
This also implies that the function is a one off, or an internal function on an object, and is most useful when you need to the features of a closure.
It's an anonymous function being called.
The purpose of that is to create a new scope from which local variables don't bleed out. For example:
var test = 1;
(function() {
var test = 2;
})();
test == 1 // true
One important note about this syntax is that you should get into the habit of terminating statements with a semi-colon, if you don't already. This is because Javascript allows line feeds between a function name and its parentheses when you call it.
The snippet below will cause an error:
var aVariable = 1
var myVariable = aVariable
(function() {/*...*/})()
Here's what it's actually doing:
var aVariable = 1;
var myVariable = aVariable(function() {/*...*/})
myVariable();
Another way of creating a new block scope is to use the following syntax:
new function() {/*...*/}
The difference is that the former technique does not affect where the keyword "this" points to, whereas the second does.
Javascript 1.8 also has a let statement that accomplishes the same thing, but needless to say, it's not supported by most browsers.
That is a self executing anonymous function. The () at the end is actually calling the function.
A good book (I have read) that explains some usages of these types of syntax in Javascript is Object Oriented Javascript.
This usage is basically equivalent of a inner block in C. It prevents the variables defined inside the block to be visible outside. So it is a handy way of constructing a one off classes with private objects. Just don't forget return this; if you use it to build an object.
var Myobject=(function(){
var privatevalue=0;
function privatefunction()
{
}
this.publicvalue=1;
this.publicfunction=function()
{
privatevalue=1; //no worries about the execution context
}
return this;})(); //I tend to forget returning the instance
//if I don't write like this
See also Douglas Crockford's excellent "JavaScript: The Good Parts," available from O'Reilly, here:
http://oreilly.com/catalog/9780596517748/
... and on video at the YUIblog, here:
http://yuiblog.com/blog/2007/06/08/video-crockford-goodstuff/
The stuff in the first set of brackets evaluates to a function. The second set of brackets then execute this function. So if you have something that want to run automagically onload, this how you'd cause it to load and execute.
John Resig explains self-executing anonymous functions here.