mixing javascript function declaration styles - javascript

Consider two styles of javascript function declarations (out of four, I think):
function foo() {
// ...
}
versus
var foo = function() {
// ...
}
In many circumstances these will behave the same, and I think I grok the main difference as explained in e.g. these SO questions:
difference-between-var-foo-function-and-function-foo
usual-functions-vs-function-variables-in-javascript
which both have answers linking to this very helpful explanation:
javascript-function-declaration-ambiguity
But I would like to combine both styles in one statement; one short/minifiable local variable name (because I will need to refer to it quite often) and one descriptive name (I want to get something friendly out of .name).
This is where I get confused. It is as if the act of immediately assigning the function to a variable leaves it undefined under its own name:
var f = function foo() {
// ...
};
console.log( f.name ); // "foo"
console.log( foo.name ); // !? error: foo is not defined ?!
So to get to the question: why does this not work? Or, more likely, what might I still be misunderstanding about these two declaration styles?
Note, that the following does not result in an error:
var f = foo;
function foo() {
// ...
}
console.log( f.name ); // "foo"
console.log( foo.name ); // "foo"
How, exactly, is this different?
PS: I think this is different from this SO question:
in-javascript-what-is-the-motivation-or-advantage-of-using-var-foo-function-f...
which is about a special case of my predicament, where the variable name and function name are the same, i.e.
var foo = function foo() {
// ...
};

When you write
var f = function foo () { ... }
the scope of foo is just the body of the function, not the enclosing function. This is mainly useful for creating anonymous recursive functions.
whats the difference between function foo(){} and foo = function(){}?
recommends against using that notation, because they don't work correctly in some implementations.

This is how I see it. Every function in javascript inherits from Function object and Function object has property .name.
this creates the function object with the name foo in the global space:
function foo(){}
this creates local anonymous(thus no name) function and assigns is to the variable f which lives in global space:
var f = function(){}
this creates the function object and assigns it to variable, it doesn't exist in global context, only local to f, the same as above, but assigns the name foo:
var f = function foo(){}
edit: for better picture consider following
(function foo(){console.log("executing foo")})();
(function(){console.log("executing anonymous")})();
are both function(objects) in global context - first with name, second without name. If they are created in variable it works the same just context is different.

Related

what is the javascript mechanism/rules that allow `p.foo = o.foo` to return a reference to the function `foo`?

I'm currently studying javascript by following the book "you dont know js" series.
In the "this & object prototype" section, when discussing "indirect references to functions", the author states
function foo() {
console.log( this.a );
}
var a = 2;
var o = { a: 3, foo: foo };
var p = { a: 4 };
o.foo(); // 3
(p.foo = o.foo)(); // 2
The result value of the assignment expression p.foo = o.foo is a
reference to just the underlying function object. As such, the
effective call-site is just foo(), not p.foo() or o.foo() as you might
expect. Per the rules above, the default binding rule applies.
So apparently, (p.foo = o.foo) return a reference to the function foo. But what is the mechanism/rules that allow (p.foo = o.foo) return a reference to the function foo? In other words, why a simple assignment return a reference to foo function?
When I want to understand something like this, I find it helpful to break it down step by step.
o.foo looks at the o object and finds a property named foo. It returns a reference that property, whatever it might be. In this case, the o.foo property is a reference to the function foo.
p.foo = o.foo takes the result from above (a reference to the function foo), creates a property in the p object which is also named foo. So now p.foo is also a reference to the foo function, exactly the same thing as o.foo.
That expression is wrapped in parentheses, so now you have whatever was on the left side of the = sign, or p.foo, which is (as a reminder) still a reference to the foo function.
Now we find the () at the end. This calls whatever function we have on hand at this moment. That is the foo function. Note in particular that we are not calling p.foo(). That would be a method call to the function that p.foo is a reference to, so inside that function, this would be set to p. But we're not doing that. We're just calling whatever function was returned by ( p.foo = o.foo ). As before, this is the same foo function, but we've now lost any connection it may have ever had to the o object or the p object.
So, when we make that call at the end, we are merely calling the foo function without setting this to any particular object. Because of that, when we make the call, this is set to undefined.
But we're not running in strict mode, so JavaScript "helpfully" doesn't want to give us an undefined this, so it sets this to the window object in a browser or the global object in Node.
Previously we did var a = 2;. So the window or global object actually now has a property named a, and the value of that property is 2.
So now when we do the console.log(this.a), we pick up the a property from the window or global object. That value is 2.
What if all this code was not running at the global level, but instead it was inside a function? What would happen then?
function test() {
function foo() {
console.log( this.a );
}
var a = 2;
var o = { a: 3, foo: foo };
var p = { a: 4 };
o.foo(); // 3
(p.foo = o.foo)(); // was 2, but now is undefined
}
test();
Now when we call console.log( this.a ); inside foo, this still refers to the window or global object. But when we set var a = 2;, we aren't setting a global property any more. We're just creating a local variable. window.a or global.a is undefined (unless some other code previously set it).
Strict mode avoids some this weirdness. If we put a 'use strict'; at the top of the code, it will compile in strict mode. And now when we make that last function call at the end, where we're calling the foo function (again not as a method!), this is now set to undefined instead of window or global. Therefore, when we try to call console.log(this.a), the code fails because this is the same as undefined, and undefined does not (and couldn't) have an a property.
Let's try it:
'use strict';
function foo() {
console.log( this.a );
}
var a = 2;
var o = { a: 3, foo: foo };
var p = { a: 4 };
o.foo(); // 3
(p.foo = o.foo)(); // was 2 in the original, but now throws an exception
The bottom line, at least for this particular example: always use strict mode! It is your friend.
The assignment operator = is an expression in JavaScript that produces (returns) the assigned value. Because it is an expression it can be used anywhere an expression is allowed, such as inside parenthesis.
For example:
let test = (a = b = c = { name: 'test' })
The code above would first evaluate the expression in the parenthesis and point the variables c, b, and a to the test object (in that order), then it would point test to the produced value from this expression. After that line is executed, a, b, c, and test will all point to the same object.
Similarly,
(p.foo = o.foo)
Would produce o.foo back (technically it would produce whatever o.foo is pointing to, which is the function foo).
As far as
(p.foo = o.foo)()
By adding the additional () after the parenths, we are telling the engine that we want to invoke whatever the expression (p.foo = o.foo) ends up producing. Thus we end up invoking the function foo. Similar patterns is used in IIFEs.
A helpful rewrite would be to think of the line above as doing this:
let produced = (p.foo = o.foo)
produced()
Further reading about statements vs expressions.

Reusable Javascript function

I'm building reusable function, but I can't change global variables values.
var foo = 5;
function MyFunction(arg) {
setInterval(function(){
foo = 2 + arg;
return foo;
}) ;
}
foo = MyFunction(1);
alert( foo );
After function complete I'm getting undefined;
Thanks in advance.
var foo = 5;
function MyFunction(arg) {
foo = 2 + arg;
}
MyFunction(1);
alert( foo );
You assigned the result of MyFunction invocation to foo and that's why you got undefined. MyFunction has no return statement.
ekuusela gives the right answer as to why your (presumably simplified) example doesn't work.
There are lots of reasons why you could have problems with globals, the most common being that you are accidentally clobbering a global by using the same identifier in some other function, and forgetting to declare it locally. To this day I still get problems where I've written for (i=0;i<n;i++) without first declaring var i in that function-- which then uses a global i, and works fine until 6 months later I make the same mistake somewhere else...
As a useful tip for debugging, the expression var G = (function(){return this})() will always give you the global object, no matter where you run it, including eval'd code. You can then access the global variable foo as G.foo, evaluate ('foo' in G) to check whether such a global exists, and so on.
In order to define a global variable you can use variable name without var keyword or define the variable outside any function scope. Then you can access it by the given method :
foo = 5;
function MyFunction(arg) {
window.foo = 2 + arg;
}
MyFunction(1);
alert( window.foo );
Note: Now foo is a part of window object.

How hoisting name resolution order works in JavaScript?

I came across a interesting quiz
function bar() {
return foo;
foo = 10;
function foo() {}
var foo = '11';
}
alert(typeof bar());
My interpretation is like this (Which is wrong according to console :) ):
var foo; // global variable
function bar(){
function foo(){}
var foo; // Here variable foo should override foo function
return foo; // (according to me foo should be variable with undefined value) What is going on here, How JavaScript resolve naming order ?
foo = 10;
foo = "11";
}
Here is a reference which I am reading this
In JavaScript, a name enters a scope in one of four basic ways:
1.Language-defined: All scopes are, by default, given the names this and arguments.
2. Formal parameters: Functions can have named formal parameters, which are scoped to the body of that function.
3. Function declarations: These are of the form function foo() {}.
4. Variable declarations: These take the form var foo;
He later quoted :
The most important special case to keep in mind is name resolution order. Remember that there are four ways for names to enter a given scope. The order I listed them above is the order they are resolved in. In general, if a name has already been defined, it is never overridden by another property of the same name. This means that a function declaration takes priority over a variable declaration. This does not mean that an assignment to that name will not work, just that the declaration portion will be ignored.
Which is confusing for me, Can anyone simplify this with reference to above example ?
Main point I want to know :
How variables without var inside a function hoisted ?
Does variable overriding occurs during hoisting ?
Lets leave the function foo for the moment. Within a function, if a variable is declared anywhere inside that function, the declaration will be moved to the top of the function. So, it is actually evaluated like this
function bar() {
var foo;
return foo;
foo = 10;
foo = '11';
}
But when you have a function declared by the same name, it will take precedence and it will be evaluated similar to this
function bar() {
var foo = function() {};
return foo;
foo = 10;
foo = '11';
}
That is why you are getting function in the alert box.
Any variable without var inside a function becomes a global variable by default.
when you have a function declaration inside another function(like in your example), it gets hoisted first followed by the variable declarations.
examples to demonstrate variable overriding.
function bar() {
var foo = 10;
function foo() {}
return foo;
}
bar(); //--> returns 10;
function bar() {
var foo;
function foo() {}
return foo;
}
bar(); //--> returns the function object foo.

What's the correct way to declare functions in a self executing function?

In the following example, why does the declaration of 'z' cause a syntax error?
(function(){
function x(){return 'this is x'};
y = function(){return 'this is y'};
//z : function(){return 'this is z'};
alert(x());
alert(y());
//alert(z());
})();
http://jsfiddle.net/VXPsd/2/
...why does the declaration of 'z' cause a syntax error?
Because you're using property initializer syntax outside of an object initializer.
This is an object initializer (the bit starting with { and ending with }) containing property initializer (the middle line):
var obj = {
propertyName: "property value"
};
So if you were declaring an object, you could use your z line (without the ;):
var obj = {
z: function() { return 'this is z'}
};
But where you have that in your code, you're not in an object initializer, you're in the body of a function. So you can't use that syntax.
It's worth noting that your x and y are quite different constructs from each other.
This:
function x(){return 'this is x'};
is a function declaration. Function declarations are processed before any step-by-step code in the containing function is run, and the function name is in scope from the top of the containing function. (Sometimes people call this "hoisting".)
This:
y = function(){return 'this is y'};
is a function expression. It's processed, like all expressions, where it's encountered in the step-by-step execution of the code in the containing function.
(The code as quoted falls prey to The Horror of Implicit Globals, btw: Since there's no var on y, and since you're not using strict mode, that line creates a global variable called y.)
What's the correct way to declare functions in a self executing function?
Neither form (the x or y form) is more correct than the other (leaving aside the implicit global thing). They each have uses, it depends on what you're doing. The y form has the issue that the function y refers to has no name (it's an anonymous function — the variable it's assigned to has a name, but the function doesn't). That can make debugging more difficult (looking at lists of breakpoints or the call stack), although modern debuggers are pretty good at showing you the variable name if the function doesn't have one, when they can.
Note that because they're not part of the step-by-step code, you cannot use a function declaration within a control structure:
function foo() {
if (condition) {
function bar() { /* ...do something... */ } // <==== WRONG
}
else {
function bar() { /* ...do something else... */ } // <==== WRONG
}
}
That's one of the reasons we have function expressions:
function foo() {
var bar;
if (condition) {
bar = function() { /* ...do something... */ }; // <==== Right
}
else {
bar = function() { /* ...do something else... */ }; // <==== Right
}
}
Note that some JavaScript engines tolerate the wrong syntax above, but the way that they tolerate it varies from engine to engine. Some engines convert the declarations into expressions for you. Others just always use the second declaration. Just don't do it. :-)
And finally: There's also something called a named function expression:
var x = function foo() { /* ... */ };
The function has a name (foo), and the variable referring to it has a name (x). It's an expression because it's used as a right-hand value (the right-hand side of an =, the : in an initializer, if you were passing it into a function as an argument, etc.) Sadly, various JavaScript engines have been known to get NFEs (as they're called) wrong in various different ways, although I think in today's world, it's really just IE8 and earlier, which create two different functions at different times.
The variableName : value syntax can only be used in the context of an object. For example:
var obj = {
z: function(){return 'this is z'};
};
In which case running obj.z() will return This is an object.
In your case you are just in the context of a function, not declaring an object. Which means you have to use the syntax you used with x or y.
The colon notation only works inside of object syntax.
For example
var theObj = {one : 'one', two : 'two'};
In order to add to the object you should use dot notation:
theObj.three = 'three';
As an executed Anonymous Function (with hiding);
var objOuter = (function(){ // Anonymous Function
var funcPrivate = function() {
// private function contents
};
var funcPublic = function() {
// private function contents
};
return { // JavaScript Object
funcName : funcPublic // provides public access to funcPublic
};
})();
//objOuter.funcPrivate(); // Failure, private.
//objOuter.funcPublic(); // Failure, internal name for public function.
objOuter.funcName(); // Executes funcPublic in objOuter's scope.
As part of a JavaScript object definition (everything is public):
var objOuter = { // JavaScript Object
funcName : function() {
// function contents
}
};
objOuter.funcName(); // Executes funcName
The Anonymous Function is executed JavaScript code, but the inside of the {} for the JavaScript object definition is a different kind of syntax that pairs keys and values.
Inside the JavaScript object you assign the value function() to key funcName. When you reference that key and execute it by passing it an argument list (), the function executes.
In the Anonymous Function (also called the Revealing Module Pattern), you are defining private functions inside the scope of the module and then passing references to those functions to the calling code as part of the returned JavaScript object.

Namespaces in JavaScript: do I need to rewrite all my variable and function references?

I am namespacing some JavaScript code, and I want to know if I have rewritten all my function calls and references to global variables correctly. The current code is this:
var x = 10;
function foo() {
console.log('foo');
bar();
},
function bar() {
console.log('bar', x);
}
foo();
I have rewritten it as follows:
var namespace = {
x : 10,
foo: function() {
console.log('foo');
// Is this the correct way to call bar?
this.bar();
},
bar: function() {
// Is this the correct way to refer to x?
console.log('bar', this.x);
}
};
namespace.foo();
Is this correct, i.e. do I need to rewrite all function calls (EDIT: by which I mean all inside the namespace variable) to this.functionname() and all global variables to this.variablename?
If you like, you can make yourself some "real" private variables and methods by incorporating a closure. I favour the module pattern.
var ns = (function () {
var x = 10;
return {
foo: function () {
console.log('foo');
this.bar();
},
bar: function () {
console.log('bar', x);
},
increment: function () {
x++;
}
}
}());
ns.foo();
ns.increment();
ns.foo();
http://jsfiddle.net/DjYue/
No, in some places (code that calls those functions from outside of your namespace object) you would have to call namespace.foo(), namespace.bar(), namespace.varName
Actually, if you use namespace.bar() from the function in the object itself, you get the added benefit that your functions don't depend on context. That is, the following code doesn't work with what you have
var fun = namespace.foo;
fun(); // This would break, since the this value is going to be the global object
I usually don't like to use this from literal objects because of the problem mentioned above. It's definitely a preference, I just prefer to avoid problems with this
No, you shouldn't rewrite to this.funcname() but rather namespace.funcname(). The this keyword is reserved to refer to the current context object (or whatever it's called), meaning that you'd use it within your "namespaced" code to refer to the namespace object.
And generally, it's good to know that you aren't actually working with namespaces as you'd know it from more classical OOP. JavaScript is a prototype-based language, which means that you don't have namespaces - rather, what you're creating is an object containing several properties and methods. As previously mentioned, when you're working with methods of the object, the this keyword refers to the object itself. You'd need a reference to the object when outside of it's context.
Currently, the approach of using objects to contain all of your code as a sort of namespaces and classes in disguise is diminishing in favor of closures which attaches the methods and properties that should be publicly available to a function (which, in JavaScript, is a first class object), and either returns that function or attaches it to the global object. You may also, alternatively, use a function to contain the properties and methods instead of an object.
I disagree with the people who say No to your question. It really depends on what you want to accomplish here. Based the rewritten code, I don't see anything wrong with it. As long as you call namespace.foo(), the execution context of each function should be namespace. Thus, it is not wrong to use this.
There is a situation that invoking the function foo() will not work:
var foo1 = namespace.foo;
foo1();
Although foo1 is same as the function namespace.foo, foo1's execution context has changed. this will refer to window, not namespace.
Their is no need to rewrite that much because you can have more than one reference to a function - a private and a public one.
var namespace = (function() {
var ns = {}; // the 'namespace'
var x = 10;
var foo = // 'private' reference: bar();
ns.foo = // 'public' reference: ns.bar() -> namespace.bar();
function foo() { // the name is optional because it's a function expression
console.log('foo');
bar();
}; // don't forget the semicolon
var bar =
ns.bar =
function() {
console.log('bar', x);
};
return ns; // return the 'namespace'
})();
namespace.foo();
var foo = namespace.foo;
foo();
delete namespace.bar;
// namespace.bar(); // Error
foo(); // bar is called

Categories

Resources