Is there any reason to think one of these methods is better or worse than the other?
function func1(x,y,z){
//do something with x,y,z
}
var x,y;
if (CONDITION){
var z;
}
// method1
if (z) {
func1(x,y,z);
}
the first method checks for z, then calls x,y,z to a function
function func2(x,y,z){
if (z){
//do something with x,y,z
}
}
var x,y;
if (CONDITION){
var z;
}
// method2
func2(x,y,z);
the second just calls the function with x,y,z knowing z is potentially undefined then checks z
edit ...
in the comments i was able to parse out what else i am asking...
... am i setting myself up for a bad time in the future should the interpreter choose to handle the undefined property differently... meaning is this an exploit, or is being able to send functions undefined variables a feature
if performance is your primary concern, as suggested by the title, I'd expect method 1 to be better. Testing z for truthiness is probably less expensive than making a function call, so you avoid the call when z is undefined. But if you want to be sure, go to jsperf.com and test it.
my concern is more with how javascript will deal with the undefineds
Consider the following (which is only visible in strict mode, hence IIFE pattern)
// A
(function () {
"use strict";
function foo(bar) {console.log('foobard');}
foo(z);
}()); // ReferenceError: z is not defined
// B
(function () {
"use strict";
var z;
function foo(bar) {console.log('foobard');}
foo(z);
}()); // foobard
// C
(function () {
"use strict";
if (false) {
var z;
}
function foo(bar) {console.log('foobard');}
foo(z);
}()); // foobard
You'll see that even if the var is inside the code block of an if that never gets it's contents executed, that var still gets applies to the names there (they'll be left undefined if they were set though). Therefore, worrying about how JavaScript will deal with the undefined is not a problem in your current pattern, which uses var for all the names before trying to reference them.
The parameter names of a function can be thought of as like another var line before the rest of the function's body, so if a parameter is named, even if undefined is passed of the function is invoked with fewer arguments than named parameters, they will not cause reference errors.
The additonnal function call should technically be more expensive in the second example, but I'm guessing that the difference is insignificant.
Also, there's nothing wrong in passing a potentially undefined value to a function. It all depends on your use cases. If it makes sense to encapsulate that undefined check in the function itself, let it be.
Finally, all variable declarations will be hoisted at the top of their scope even if they appear at other places in the code. Basically, as long as you are only declaring a variable, but not initializing it, there's no difference if you put the declaration in a if statement or not.
Related
I just started to learn about javascript etc, and I get a project from my friend to take a look at it, and what I saw there is that they are using javascript functions all the time as a function expression, like this:
var a = function(Id) {
//Do something here
}
I could say like ok, they'r working like that and I'm gonna work like that also like robot, even if I don't understand why is that like that..
So I'm wondering what is this acctually, (in that code I posted above) is that function called "a" which is expecting 1 argument called "Id" in our case so I could call it on click of some button for example, or maybe this var a is acctually variable which is called "a" but it might be called as a function and acctually it is a javascript function?
This is little bit confusing me here, and I saw in this project that almost all javascrit functions are used like this, but is this a right approach or they should use named functions expression so it might look like this:
var a = function myFunction(Id) {
//Do something here
}
So what is this now ? I created function called myFunction which is expecting 1 argument called "Id" and it could be called on click by myFunction and also by calling "a" varible ? (if it is variable, or it is also function name or whatever)..
Thanks guys
Cheers
The key to understanding this is that, in JavaScript, functions are data, just like any other. So, if you are ok understanding this:
var x = 10;
If you were to try to get the value of x, you'd get 10:
console.log(x);
Then, understanding this isn't that much of a stretch:
var x = function(){
// do something
}
if you were to try to get the value here, you'd get the actual text of the function:
console.log(x); // function(){ // do something }
Since this last version retrieves a function, you could then invoke the function by simply appending () to the returned value, like this:
x(); // This would invoke the function stored in x
The alternative approach is with a "function declaration" which looks like this:
function x(){
// Do something
}
Here, there is no variable storing the function...x is the function and to invoke it, you'd do it directly:
x();
However, in JavaScript, all declarations are "hoisted" to the top of their enclosing scope, so this:
var x = function(){};
would cause the declaration of x to be hoisted, but not the value of x, while this:
function x(){ ...};
would cause the entire declaration to be hoisted.
The difference is that a declaration would allow you to invoke the function in code the precedes the actual declaration (since hoisting would cause the function to be read first) and with an expression, if you tried this, you would get an error stating that x is not a function.
Here's an example of this:
// Print the return value from runing the function who's name is "x".
// This will succeed even though we haven't even declared the function x yet becuase all
// declarations are hoisted to the top of their enclosing scope;
console.log(x());
// Print the return value from runing the function stored in the variable called "y":
// This will fail with an error stating that y is not a function because only the variable
// declaration (var y) is hoisted to the top of the enclosing scope, but not the value assigned to it.
console.log(y());
// This is a function "declaration" for a function who's name is "x"
function x(){
return "hello from function declaration x";
}
// This is a function expression being assigned as the data for a variable
var y = function(){
return "hello from function expression y";
}
Both are useful and often interchangeable, but hoisting causes differences in how (and when) you can call the function.
I won't claim that I'm terribly well versed in Node, or even Javascript, but I've seen several modules of the form
module.exports = foo;
function foo() {
...
}
Now, I could see this working perhaps in this case, but I'm really confused when that module returns a function that is excuted.
module.exports = bar();
function bar() {
...
}
What is this witchcraft?
Functions are defined at parse time, assignments are assigned at runtime. See this article http://javascriptweblog.wordpress.com/2010/07/06/function-declarations-vs-function-expressions/ for more.
In short, the compiler makes 2 passes. With the following code:
var a = x;
function x( ) { }
In the first pass, var a and function x are declared and available in a symbol table (or some other form depending on the interpreter) after which the compiler makes a second pass performing the assignment of function x as to var a. At this stage, at any point (but limited to the language rules), function x is known.
As far as I know, function foo() { aaa(); } is just var foo = function(){ aaa() } in JavaScript. So adding function foo() { bbb(); } should either overwrite the foo variable, or ignore the second definition - that's not the point. The point is that there should be one variable foo.
So, in this example the me variable should not be correctly resolved from inside the methods and it is not in Explorer 8 :-). I came to this example by trying to wrap them into another closure where (var) me would be, but I was surprised that it's not necessary:
var foo = {
bar1 : function me() {
var index = 1;
alert(me);
},
bar2 : function me() {
var index = 2;
alert(me);
}
};
foo.bar1(); // Shows the first one
foo.bar2(); // Shows the second one
Demo: http://jsfiddle.net/W5dqy/5/
AFAIK function foo() { aaa(); } is just var foo = function(){ aaa() } in JavaScript.
Not quite; they're similar, but also quite different. JavaScript has two different but related things: Function declarations (your first example there), and function expressions (your second, which you then assign to a variable). They happen at different times in the parsing cycle and have different effects.
This is a function declaration:
function foo() {
// ...
}
Function declarations are processed upon entry into the enclosing scope, before any step-by-step code is executed.
This is a function expression (specifically, an anonymous one):
var foo = function() {
// ...
};
Function expressions are processed as part of the step-by-step code, at the point where they appear (just like any other expression).
Your quoted code is using a named function expression, which look like this:
var x = function foo() {
// ...
};
(In your case it's within an object literal, so it's on the right-hand side of an : instead of an =, but it's still a named function expression.)
That's perfectly valid, ignoring implementation bugs (more in a moment). It creates a function with the name foo, doesn't put foo in the enclosing scope, and then assigns that function to the x variable (all of this happening when the expression is encountered in the step-by-step code). When I say it doesn't put foo in the enclosing scope, I mean exactly that:
var x = function foo() {
alert(typeof foo); // alerts "function" (in compliant implementations)
};
alert(typeof foo); // alerts "undefined" (in compliant implementations)
Note how that's different from the way function declarations work (where the function's name is added to the enclosing scope).
Named function expressions work on compliant implementations. Historically, there were bugs in implementations (early Safari, IE8 and earlier). Modern implementations get them right, including IE9 and up. (More here: Double take and here: Named function expressions demystified.)
So, in this example the me variable shoudl not be corectly resolved from inside the methods
Actually, it should be. A function's true name (the symbol between function and the opening parenthesis) is always in-scope within the function (whether the function is from a declaration or a named function expression).
NOTE: The below was written in 2011. With the advances in JavaScript since, I no longer feel the need to do things like the below unless I know I'm going to be dealing with IE8 (which is very rare these days).
Because of implementation bugs, I used to avoid named function expressions. You can do that in your example by just removing the me names, but I prefer named functions, and so for what it's worth, here's how I used to write your object:
var foo = (function(){
var publicSymbols = {};
publicSymbols.bar1 = bar1_me;
function bar1_me() {
var index = 1;
alert(bar1_me);
}
publicSymbols.bar2 = bar2_me;
function bar2_me() {
var index = 2;
alert(bar2_me);
}
return publicSymbols;
})();
(Except I'd probably use a shorter name than publicSymbols.)
Here's how that gets processed:
An anonymous enclosing function is created when the var foo = ... line is encountered in the step-by-step code, and then it is called (because I have the () at the very end).
Upon entry into the execution context created by that anonymous function, the bar1_me and bar2_me function declarations are processed and those symbols are added to the scope inside that anonymous function (technically, to the variable object for the execution context).
The publicSymbols symbol is added to the scope inside the anonymous function. (More: Poor misunderstood var)
Step-by-step code begins by assigning {} to publicSymbols.
Step-by-step code continues with publicSymbols.bar1 = bar1_me; and publicSymbols.bar2 = bar2_me;, and finally return publicSymbols;
The anonymous function's result is assigned to foo.
These days, though, unless I'm writing code I know needs to support IE8 (sadly, as I write this in November 2015 it still has significant global market share, but happily that share is plummetting), I don't worry about it. All modern JavaScript engines understand them just fine.
You can also write that like this:
var foo = (function(){
return {
bar1: bar1_me,
bar2: bar2_me
};
function bar1_me() {
var index = 1;
alert(bar1_me);
}
function bar2_me() {
var index = 2;
alert(bar2_me);
}
})();
...since those are function declarations, and thus are hoisted. I don't usually do it like that, as I find it easier to do maintenance on large structures if I do the declaration and the assignment to the property next to each other (or, if not writing for IE8, on the same line).
Both me lookups, are only visible/available inside the function expression.
Infact those two are named function expressions, and the ECMAscript specification tells us, that the name of an expression is not exposed to the such called Variable object.
Well I tried to put that only in a few words, but while trying to find the right words, this ends up in pretty deep chain of ECMAscript behavior. So, function expression are not stored in a Variable / Activation Object. (Would lead to the question, who those guys are...).
Short: Every time a function is called, a new Context is created. There is some "blackmagic" kind of guy that is called, Activation object which stores some stuff. For instance, the
arguments of the function
the [[Scope]]
any variables created by var
For instance:
function foo(test, bar) {
var hello = "world";
function visible() {
}
(function ghost() {
}());
}
The Activation Object for foo would look like:
arguments: test, bar
variables: hello (string), visible (function)
[[Scope]]: (possible parent function-context), Global Object
ghost is not stored in the AO! it would just be accesssible under that name within the function itself. While visible() is a function declaration (or function statement) it is stored in the AO. This is because, a function declaration is evaluated when parsing and function expression is evaluated at runtime.
What happens here is that function() has many different meanings and uses.
When I say
bar1 : function me() {
}
then that's 100% equivalent to
bar1 : function() {
}
i.e. the name doesn't matter when you use function to assign the variable bar1. Inside, me is assigned but as soon as the function definition is left (when you assign bar2), me is created again as a local variable for the function definition that is stored in bar2.
I'm a bit confused. What is the purpose of the parameters when you initiate an anonymous member pattern designated below:
(function (<ParameterA>) {
})(<ParameterB>);
I understand that Parameter A is used to designate the scope of the function is this true?
Is ParameterB where you export the function?
Finally, I often see script indicating the following:
})(jQuery || myfunc);
Does that mean they're exporting these or returning these objects? And what's the point of using the two pipes (||); It a field goal thing?
Thanks in advance. Looking forward to interesting discussion.
Parameter A does not designate the scope of the function. The function's position determines the scope of the function. ParameterB is not where you export the function. In fact, the way this is set up, there is no pointer to the function anywhere which makes it an "anonymous function." In other words, as is, the function itself is un-exportable. Usually when you talk about exporting things, you're talking about exporting variables that you defined inside anonymous functions. For example, here I am exporting the function my_inner_function from an anonymous function.
(function (<ParameterA>) {
// export this function here.
window.my_inner_function = function() {
...
};
})(<ParameterB>);
Usually, the point of anonymous functions is that you have all kinds of variables that you don't want to export because you don't want to possibly muck with other code.
(function (<ParameterA>) {
// convert could be defined somewhere else too, so to be on the safe side
// I will hide it here in my anonymous function so nobody else can
// reference it.
var convert = function() {
...
};
})(<ParameterB>);
This is particularly important when you compress your Javascript and get function names like a and b.
(function (<ParameterA>) {
// So compressed!
var a = function() {
...
};
})(<ParameterB>);
(function () {
// Another compressed thing! Good thing these are hidden within anonymous
// functions, otherwise they'd conflict!
var a = function() {
...
};
})();
Now this
(function (<ParameterA>) {
})(<ParameterB>);
is the same thing as
// Assume ParameterB is defined somewhere out there.
(function () {
var ParameterA = ParameterB;
})();
Which gives you an idea why you'd use the parameters. You may find the parameter approach less confusing, or you may want to make it clear that you don't want to affect "by value" variables such as numbers and strings.
As others have pointed out, a || b is spoken as "a or b" and means "a if a evaluates to true, otherwise b, no matter what b is."
Edit
To answer your question, when you get to })(); the () causes the anonymous function to run. Remember that Javascript engines will first parse all code to make sure the syntax is correct, but won't actually evaluate/execute any code until it reaches that code. Hence, it's when the anonymous function runs that var ParameterA = ParameterB; gets evaluated. Here are some examples that hopefully help.
var ParameterB = "hello";
(function () {
var ParameterA = ParameterB;
// alerts "hello" because when this line is evaluated ParameterB is still
// "hello"
alert(ParameterA);
})(); // () here causes our anonymous function to execute
ParameterB = "world";
Now in this example, the function is no longer anonymous because it has
a pointer. However, it acts the same as the previous example.
var ParameterB = "hello";
var myFunction = function () {
var ParameterA = ParameterB;
// alerts "hello" because when this line is evaluated ParameterB is still
// "hello"
alert(ParameterA);
};
myFunction();
ParameterB = "world";
In this example, I change the order of the last 2 lines and get different
results.
var ParameterB = "hello";
var myFunction = function () {
var ParameterA = ParameterB;
// alerts "world" because when this line is evaluated ParameterB has
// already changed.
alert(ParameterA);
};
// notice that I moved this line to occur earlier.
ParameterB = "world";
myFunction();
The code block above executes an anonymous function immediately after declaring it.
ParameterA is a parameter to the anonymous function you are declaring
ParameterB is the value you are passing to ParameterA
So the function you declared will be executed immediately, passing ParameterB as the value for ParameterA.
The jQuery || myFunc block means this: use jQuery as the argument unless it is not defined, in which case use myFunc.
Edit:
This is often used when defining jQuery plugins to avoid conflicts with the $ variable if multiple javascript libraries are being used. So you would make your plugin definition a function that accepts $ as a parameter, which you would execute immediately, passing jQuery as the value to $.
Example (from jQuery docs):
(function( $ ){
$.fn.myPlugin = function() {
// Do your awesome plugin stuff here
};
})( jQuery );
The result of the above code block will be a plugin definition where you are guaranteed that $ will be an alias for jQuery.
For parts 1 and 2, ParameterA could be used to alias a nested hierarchy. (ie: YAHOO.util.Event passed in as ParameterB, can be used as "e" in ParameterA.) That way, inside the anonymous function, you wouldn't be typing out the full namespace path. [I know you're a jquery guy, but the yahoo namespace is longer, and illustrates the point better :)] Alternatively, you could just manually store the reference in a var inside the function.
the jquery || myFunc syntax is shorthand for "use jquery if it is truthy/available, or myFunc if it is not".
It's sort of like var toUse = jQuery !== undefined ? jQuery : myFunc;
This is because javascript allows falsy value evaluation without converting the objects fully to a boolean. ie: undefined is falsy, "" is falsy, null is falsy.
The alternative can be used to detect if a method or property is even available with &&.
ie: var grandParent = person && person.parent && person.parent.parent;
This will only be defined if the person has a parent, and their parent has a parent. Any failure along the && leading up to the last statement will result in grandParent being undefined.
Lastly, the parens around the || shortcut syntax are basically executing the function immediately after the declaration, passing the evaluated value into the anonymous function.
ie: (function(a, b) { return a + b; })(2,3)
Will immediately execute and return 5. In practice, this anonymous function execution could be used with the module pattern to establish a set of public methods which use private functions that themselves do not appear in the page's namespace. This is more in depth than your original question, but you can check out this article for more information: http://yuiblog.com/blog/2007/06/12/module-pattern/
ParameterA is referencing the value passed in at ParameterB. This:
(function (<ParameterA>) {
})(<ParameterB>);
Is sort of the same as this:
function test(<ParameterA>) {
}
test(<ParameterB>);
The difference is that this way you are using a closure to not have conflicting functions in the global namespace.
For the second part: the || work sort of like param = jQuery ? jQuery : myFunc. It passes in jQuery if it is defined, or myFunc if it isn't.
With your first part:
(function (<ParameterA>) {
})(<ParameterB>);
This means that the variable known as ParameterB outside the function will be known as ParameterA inside the function. This is known as a self-executing function, because the function is called as soon as it is defined. It means that you can use ParameterA inside the function without overriding a variable that exists outside the function.
For instance:
(function($){
})(jQuery);
This means that you can have $ as, for instance, Mootools outside the function and as jQuery inside it.
With your second part:
})(jQuery || myfunc);
This calls the function passing the jQuery variable if it exists, and myfunc if it does not. I don't quite know why you'd do this...
I've written (in JavaScript) an interactive read-eval-print-loop that is encapsulated
within an object. However, I recently noticed that toplevel function definitions specified to the interpreter do not appear to be 'remembered' by the interpreter. After some diagnostic work, I've reduced the core problem to this:
var evaler = {
eval: function (str)
{
return eval(str);
},
};
eval("function t1() { return 1; }"); // GOOD
evaler.eval("function t2() { return 2; }"); // FAIL
At this point, I am hoping that the following two statements wil work as expected:
print(t1()); // => Results in 1 (This works)
print(t2()); // => Results in 2 (this fails with an error that t2 is undefined.)
What I get instead is the expected value for the t1 line, and the t2 line fails with an error that t2 is unbound.
IOW: After running this script, I have a definition for t1, and no defintion for t2. The act of calling eval from within evaler is sufficiently different from the toplevel call that the global definition does not get recorded. What does happen is that the call to
evaler.eval returns a function object, so I'm presuming that t2 is being defined and stored in some other set of bindings that I don't have access to. (It's not defined as a member in evaler.)
Is there any easy fix for this? I've tried all sorts of fixes, and haven't stumbled upon one that works. (Most of what I've done has centered around putting the call to eval in an anonymous function, and altering the way that's called, chainging __parent__, etc.)
Any thoughts on how to fix this?
Here's the result of a bit more investigation:
tl;dr: Rhino adds an intermediate scope to the scope chain when calling a method on an instance. t2 is being defined in this intermediate scope, which is immediately discarded. #Matt: Your 'hacky' approach might well be the best way to solve this.
I'm still doing some work on the root cause, but thanks to some quality time with jdb, I now have more understanding of what's happening. As has been discussed, a function statement like function t1() { return 42; } does two things.
It creates an anonymous instance of a function object, like you'd get with the expression function() { return 42; }
It binds that anonymous function to the current top scope with the name t1.
My initial question is about why I'm not seeing the second of these things happen when I call eval from within a method of an object.
The code that actually performs the binding in Rhino appears to be in the function org.mozilla.javascript.ScriptRuntime.initFunction.
if (type == FunctionNode.FUNCTION_STATEMENT) {
....
scope.put(name, scope, function);
For the t1 case above, scope is what I've set to be my top-level scope. This is where I want my toplevel functions defined, so this is an expected result:
main[1] print function.getFunctionName()
function.getFunctionName() = "t1"
main[1] print scope
scope = "com.me.testprogram.Main#24148662"
However, in the t2 case, scope is something else entirely:
main[1] print function.getFunctionName()
function.getFunctionName() = "t2"
main[1] print scope
scope = "org.mozilla.javascript.NativeCall#23abcc03"
And it's the parent scope of this NativeCall that is my expected toplevel scope:
main[1] print scope.getParentScope()
scope.getParentScope() = "com.me.testprogram.Main#24148662"
This is more or less what I was afraid of when I wrote this above: " In the direct eval case, t2 is being bound in the global environment. In the evaler case, it's being bound 'elsewhere'" In this case, 'elsewhere' turns out to be the instance of NativeCall... the t2 function gets created, bound to a t2 variable in the NativeCall, and the NativeCall goes away when the call to evaler.eval returns.
And this is where things get a bit fuzzy... I haven't done as much analysis as I'd like, but my current working theory is that the NativeCall scope is needed to ensure that this points to evaler when execution in the call to evaler.eval. (Backing up the stack frame a bit, the NativeCall gets added to the scope chain by Interpreter.initFrame when the function 'needs activation' and has a non-zero function type. I'm assuming that these things are true for simple function invocations only, but haven't traced upstream enough to know for sure. Maybe tomorrow.)
Your code actually is not failing at all. The eval is returning a function which you never invoke.
print(evaler.eval("function t2() { return 2; }")()); // prints 2
To spell it out a bit more:
x = evaler.eval("function t2() { return 2; }"); // this returns a function
y = x(); // this invokes it, and saves the return value
print(y); // this prints the result
EDIT
In response to:
Is there another way to create an interactive read-eval-print-loop than to use eval?
Since you're using Rhino.. I guess you could call Rhino with a java Process object to read a file with js?
Let's say I have this file:
test.js
function tf2() {
return 2;
}
print(tf2());
Then I could run this code, which calls Rhino to evaluate that file:
process = java.lang.Runtime.getRuntime().exec('java -jar js.jar test.js');
result = java.io.BufferedReader(java.io.InputStreamReader(process.getInputStream()));
print(result.readLine()); // prints 2, believe it or not
So you could take this a step further by WRITING some code to eval to a file, THEN calling the above code ...
Yes, it's ridiculous.
The problem you are running into is that JavaScript uses function level scoping.
When you call eval() from within the eval function you have defined, it is probably creating the function t2() in the scope of that eval: function(str) {} function.
You could use evaler.eval('global.t2 = function() { return 2; }'); t2();
You could also do something like this though:
t2 = evaler.eval("function t2() { return 2; }");
t2();
Or....
var someFunc = evaler.eval("function t2() { return 2; }");
// if we got a "named" function, lets drop it into our namespace:
if (someFunc.name) this[someFunc.name] = someFunc;
// now lets try calling it?
t2();
// returns 2
Even one step further:
var evaler = (function(global){
return {
eval: function (str)
{
var ret = eval(str);
if (ret.name) global[ret.name] = ret;
return ret;
}
};
})(this);
evaler.eval('function t2() { return 2; }');
t2(); // returns 2
With the DOM you could get around this function-level scoping issue by injecting "root level" script code instead of using eval(). You would create a <script> tag, set its text to the code you want to evaluate, and append it to the DOM somewhere.
Is it possible that your function name "eval" is colliding with the eval function itself? Try this:
var evaler = {
evalit: function (str)
{
return window.eval(str);
},
};
eval("function t1() { return 1; }");
evaler.evalit("function t2() { return 2; }");
Edit
I modified to use #Matt's suggestion and tested. This works as intended.
Is it good? I frown on eval, personally. But it works.
I think this statement:
evaler.eval("function t2() { return 2; }");
does not declare function t2, it just returns Function object (it's not function declaration, it's function operator), as it's used inside an expression.
As evaluation happens inside function, scope of newly created function is limited to evaler.eval scope (i.e. you can use t2 function only from evaler.eval function):
js> function foo () {
eval ("function baz() { return 'baz'; }");
print (baz);
}
js> foo ();
function baz() {
return "baz";
}
js> print(baz);
typein:36: ReferenceError: baz is not defined
https://dev.mozilla.jp/localmdc/developer.mozilla.org/en/core_javascript_1.5_reference/operators/special_operators/function_operator.html
https://dev.mozilla.jp/localmdc/developer.mozilla.org/en/core_javascript_1.5_reference/statements/function.html
I got this answer from the Rhino mailing list, and it appears to work.
var window = this;
var evaler = {
eval : function (str) {
eval.call(window, str);
}
};
The key is that call explicitly sets this, and this gets t2 defined in the proper spot.