Is there any difference if I wrap a function inside another? - javascript

What is the difference between these two?
I import both in browserify and they seem to give the same result.
Is there any difference between them and how they work?
var App = (function () {
var Foo = function (name) {
this.name = name;
};
Foo.prototype.logout = function () {
console.log();
}
return Foo;
})();
module.exports = App;
VS
var Foo = function (name) {
this.name = name;
};
Foo.prototype.logout = function () {
console.log();
}
module.exports = Foo;

In this particular case, the only difference is that in the first code sample you end up with a variable named "App", and in the second you end up with one named "Foo". Other than that effect on the namespace, the two do the same thing.
More generally, code that looks like this:
var x = function() {
// lots of stuff
return something;
}();
allows for "lots of stuff" to be done in a context that's isolated from the surrounding context. That means that functions and variables defined inside that anonymous function won't "leak out" into the surrounding context unless that's an explicit goal of the return statement (or other code that otherwise affects some outer context somehow, most typically by direct modifications to window or something like the jQuery prototype).
In your example, again, the "lots of stuff" in the second example didn't involve altering any namespace other than that function prototype, which the first code does too.

Yes, there is difference between these two. First example keeps you safe from polluting your global scope with Foo variable, since it's wrapped in IFEE(Immediately Invoked Function Expressions) and assigned to variable App. Since Foo is inside IFEE it belongs to IFEE's scope.
Foo variable from second example is in global scope and if you import this file in some other code Foo would override variable from that file if there also exist variable with that name. So to be sure that this wouldn't happen it's better to wrap imported code into IFEE.
Also, accessing variable Foo is different, in first example you would access it with App.Foo (since it's namespaced under App) and in second you access it with Foo.

Related

Checking if an attribute gets attached to $scope

This question really consists of two:
1 - Do functions create their own $scopes in javasript?
e.g.$scope.foo = function() {
$scope.bar = "Bar";
}
I ask this because in one such test that I'm trying to run I check to determine the existence of a variable on the scope, run a function and then recheck:
iit('getPatientFirstName should attach patientName to the scope', function() {
// Passes
expect(scope.patientName).toBeUndefined();
spyOn(scope,'getPatientFirstName').andCallThrough();
scope.getPatientFirstName(detailsBody);
// Fails
expect(scope.patientName)not.toBeUndefined();
});
// In the controller
$scope.getPatientFirstName = function (dataBody) {
$scope.patientName = dataBody.patientFirstName;
};
So this suggests that they may have their own scope? If this is the case can we test this?
2 - Is a valid alternative just to use an object that exists outside the function:
$scope.patientDetails = {
patientName: ''
};
$scope.getPatientFirstName = function (dataBody) {
$scope.patientDetails.patientName = dataBody.patientFirstName;
};
Thanks
EDIT
Considering the two answers has raised another question - is a variable (attribute or object) considered global if its attached to the $scope? It can be accessed in any function in that controller but as far as being called in a completely different controller - yes it can?
Confirm/Deny anyone?
And it appears that assigning the variable to the $scope global is considered valid for the purposes of my test.
Regarding your first questions, no, functions do not create new $scopes by their own (note that we are talking about scopes and not closures, which are two different concepts).
In your example, the $scope.foo function creates a new bar property on the same $scope object where foo is defined. The final $scope object would look something like this:
$scope {
foo: function() {
$scope.bar = "Bar";
},
bar: "Bar"
}
The problem with your test may be related to the missing . before the not.
expect(scope.patientName).not.toBeUndefined();
Is a valid alternative just to use an object that exists outside the
function:
Yes, you can use an object that's defined outside the function.
If the object is on the same $scope object you will have no problems, just make sure it is defined before you run the function, otherwise you will get a $scope.patientDetails is not defined error.
I'll answer the question a little differently than where you are taking it. I hope it helps you to rethink your stategy.
1 - Do functions create their own $scopes in javasript?
They do create an own scope. But the surrounding scope is also available within the scope. So when you write a function within a function, the inner function can use all the variables of the outer function
Example
function foo() {
var a=5;
function bar() {
var b=4;
}
function hello() {
var c=3;
}
}
a is available for all the functions, foo, bar and hello.
b is not available for foo nor for hello.
c is not available for foo nor for bar.
2 - Is a valid alternative just to use an object that exists outside the function:
So, you should try to make an outer function; there you can declare variables that will be strictly contained within that outer function.
Any function you create within this outer function can make use of that outer scope.
Variables that are global should be avoided if possible.
An example: jQuery.
jQuery has 1 variable that is global: var jQuery ( You can also access it by its alias $ ).
The variables that jQuery uses will not be in conflict with any variables you use.
And anything you want from jQuery, you will have to go through $ (or jQuery)

Access Property from External Function

I am trying to setup a feature as follows.
function Class() {
}
Class.prototype.func = function(f) {
var hello = "hello";
setTimeout(f, 1000);
};
new Class().func(function() {
alert(hello);
});
I want the f() function to be able to access the hello variable. The problem is that f() is not running in the context of the func() function.
I have tried using var hello = "hello"; and this.hello = "hello"; but neither work.
How can f() access hello?
Pass it as a parameter
function Class(){
}
Class.prototype.func=function(f){
var hello="hello";
setTimeout(function(){
f(hello)
},1000);
};
new Class().func(function(hello){
alert(hello);
});
Given the structure of the code you've got, there's no way for any "f" passed into "func" to access "hello".
You could however, do this:
Class.prototype.func=function(f){
this.hello="hello";
setTimeout(f.bind(this),1000);
};
new Class().func(function(){
alert(this.hello);
});
JavaScript scoping is based on the lexical relationship between functions (declaring contexts). A variable declared with var is available to the function in which it's declared, and to all functions declared/instantiated within that function. In your case, the anonymous function is not declared inside "func", so no local variable of "func" can ever be visible to it. There's no way to dynamically expose the local scope from inside "func" either. (I generally forget about ignore eval() when answering questions like this, but here I don't think even eval() could work around the situation.)
It can't. The variable simply does not exist in the scope in which the function is defined.
You would need to expose it to a wider scope (e.g. by making it a property of the instance of the Class object or a global).

js pattern problems

I'm confused by a javascript design pattern I'm reading about:
var class = (function() {
...a bunch of code...
return {
.. some more code..
;
// or, in some cases
return function(constructorArgs) {
};
})();
My question is: What is the return statement doing? Why is it there? I'm confused because no-one wants to mention it or talk about it.
There's two distinct patterns that you're mentioning, I think.
Anonymous Closures
The first is using an anonymous function to wrap a block of code in order to create a closure:
var outer = (function() {
var inner = "now you see me!";
return inner + " now you don't"
})()
The anonymous function creates a new scope for var-defined variables. In effect, this allows you to define variables that are only visible within that particular function.
In the example above, you have access to inner within the function, but it is not defined outside of it.
"Classes"
The second is a common pattern for defining "classes" in JavaScript:
var MyClass = (function() {
function MyClass(arg) {
this.arg = arg
}
return MyClass
})()
By defining the constructor function within a closure, you can be sure that your class is well contained. It also enables you to share class-wide state or private helper methods without polluting the global namespace, or resorting to placing them as properties on your class constructor's prototype.
the code to the right of the = symbol is of this form: (function(){})(); What this does is compile a function - effectively the same as the following:
function temp() {
}
class = temp();
Inside the function in your example, however, there is another function being returned. What this means is that class is now also a function - the class function can then reference all of the variables etc. that are declared in the temp function, due to the closure effect referenced by vtortola.
The idea of this is to allow the inner function to refer to some state that you don't want to have hanging around in your "global" (or semi-global) scope - it doesn't matter where the class method is called, or who by, it will always have access to that data.
Edit: It appears from the code that the purpose of the pattern in this case is to create a "class" type function - so then you'd be able to call it with the following code:
var myInstance = new class();
Though I've a feeling that none of the code will work as I'm reasonably certain that class is a reserved word...
This is called a closure.
var myVar = (function (param1, param2){
//do things
}('myParam1','myParam2')):
The javascript engine will immediatly execute what is between the parenthesis.
And the value of myVar will be what the function function (param1, param2){ ... } returns.
This function will use ('myParam1','myParam2') as arguments.
You can write closure in two different ways :
(function (receivedArgs){
//do things
})(yourArguments);
or
(function (receivedArgs){
//do things
}(yourArguments));
It is a closure. A function is returning an inner function enclosing some variables in the middle.
https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Closures
Cheers.

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

Trying to figure out how scope works

I'm trying to learn JS on codeacademy and I can't understand/get past this thing. Can someone please provide an answer and also an explanation of why is it so? Would deeply appreciate.
// This function tries to set foo to be the
// value specified.
function setFoo(val) {
// foo is declared in a function. It is not
// accessible outside of the function.
var foo = val;
}
setFoo(10);
// Now that we are outside the function, foo is
// not defined and the program will crash! Fix this
// by moving the declaration of foo outside of the
// function. Make sure that setFoo will still update
// the value of foo.
alert(foo);
You can see scope as a term meaning what variables you can reach at a specific "level" in the code. In JavaScript, these "levels" are defined by functions. Each function introduces a new level.
For example, take this sample code:
var a;
// you can access a at this level
function function1() {
var b;
// you can access a, b at this level
function function2() {
var c;
// you can access a, b, c at this level
}
}
So in your case, you should declare var foo; outside the function, preferably above it. Then you can set it inside setFoo with foo = val;. foo then refers to the one you declared in the level above setFoo.
foo is accessible both in setFoo and in the alert call that way; compare it with the above sample code (function1 is setFoo, a is foo and the alert call is in the top-most level. function2, b and c are not used in your case.).
// Create globale variable
// (You should not use globale variables!)
var foo;
// set value
function setFoo(val) {
foo = val;
}
setFoo(10);
// show value
alert(foo);
Just declare foo outside any function then it will be global:
var foo = null;
function setFoo(val) {
foo = val;
}
setFoo(10);
alert(foo);
Try it !
When you declare a variable in Javascript it is only visible to code that is in the same function as it is declared, or a function inernal to that function. Because foo is originally declared in the SetFoo function nothing outside of SetFoo is able to see it, so the call to alert fails as foo does not exist in the gloabl scope.
As the comments suggest, moving the declaration of foo out of the function and into the global scope (which you can think of as a catch-all function that contains everything) would allow you to use foo when calling alert.
var foo;
function setFoo(val) {
foo = val;
}
setFoo(10);
alert(foo); // No longer crashes
Every function in Javascript has it's own scope. That means that every variable you define there with the var keyword, will only be available within that function. That means that when you call setFoo(10), you create the variable foo, give it a value of five, after which it is immediately destroyed because it went out of scope.
There are multiple ways to solve this problem. The first would be to remove the var keyword. This would put foo in the global scope, which means that it's available everywhere. However, this is discouraged, you want to keep the global scope as uncluttered as possible, so that if you have javascript code provided by multiple people on the same page, they can't overwrite other people's variables. Another way to do it would be this:
function setFoo(val){
var foo = val;
alertfoo = function(){
alert(foo)
}
}
In this example, the only thing you're putting in the global scope is the alertfoo function, because you want that to be available everywhere. The alertfoo function is defined inside the setFoo function, this means that although foo should have gone out of scope after setfoo has been executed, it is kept in memory, because alertfoo has access to it.
This makes for some nice tricks. For example, let's say you're making a javascript library that will be included on other people's pages, you'll want to create a scope inside of which you can define variables, without polluting the global scope. The most common way to do this, is by declairing a self-executing function. This is a function which is executed immediately after being defined, it looks like this:
(function(){
//set variables you want to be global in your own code
var mainpage = document.getElementById('main');
//define functions you want to make available to other people in a way that puts them in the global scope
setMainElement = function(newmain){mainpage = newmain;}
})();
You can make this even better by making only one object global, and provide your interfae through the methods of that object, this way, you create a namespace with all the functions that your library contains. The next example uses an object literal to do this. In javascript, you can create an object by putting key/value pairs petween curly braces. the key/value pairs are properties of the object. for example:
(function(){
var privatevar = 10,otherprivate=20;
publicInterface = {
'addToPrivate': function(x){privatevar+=x;},
'getPrivate': function(){return private}
};
})();
Original code:
function setFoo(val) {
var foo = val;
}
setFoo(10);
alert(foo); // Crash!
Their advice to fix the crash:
Fix this by moving the declaration of foo outside of the function
I'm guessing you're confused as to what they mean by "outside of the function".
Try this edited code:
var foo = 5; // "var" declares the variable to be in this outer scope
function setFoo(val) {
foo = val; // but we can still access it in this inner scope...
}
setFoo(10);
alert(foo); // Displays a dialog box that says "10"
Variables defined in the function is valid only in the function
function setFoo(val) {
foo = val;
}
In JavaScript, new scopes are only created by functions

Categories

Resources