I am currently working on modules but my confusion is that when I code return object in function it can called outside function scope, but when I code standard object like var obj = {some: something} then this can't be called outside the function scope. Why and how?
// Return Object
var ray = (function(){
return {
speak: function (){
console.log("Haseeb");
}
};
})();
ray.speak();
// Standard Object
var ray = (function(){
var obj = {
speak: function (){
console.log("Haseeb");
}
}
})();
obj.speak();
Assuming that you meant to write ray.speak(); instead of obj.speak();;
// Standard Object
var ray = (function(){
var obj = {
speak: function (){
console.log("Haseeb");
}
}
})();
In this snippet, when anonymous function is executed it returns nothing back to ray variable, so when you try to access speak() method from ray, it throws an error saying Cannot read property 'speak' of undefined.
But in your first snippet, the anonymous function does return an object with speak method so you can call, ray.speak().
// Standard Object
var ray = (function(){
var obj = {
speak: function (){
console.log("Haseeb");
}
}
})();
obj.speak();
This does not work because of how lexical scoping works. Obj on the outside has no context to what is defined inside of the function because the obj is declared inside the block scope of the function. If, however obj was declared in the same scope, it will work as expected.
var obj;
// Standard Object
var ray = (function(){
obj = {
speak: function (){
console.log("Haseeb");
}
}
})();
obj.speak();
ray.speak() will not work because it does not have a binding to obj.
return obj={...} will be a solution for this problem.
Understanding JavaScript variable scope would help:
http://www.w3schools.com/js/js_scope.asp
Now coming to your code.
In the first snippet, the variable 'ray' gets assigned the value returned by the the self executed function, which is the object returned. It is similar to this:
var ray = {
speak: function (){
console.log("Haseeb");
}
};
So now the statement below is valid as 'ray' has a property 'speak'
ray.speak();
However, in the second part of the snippet, nothing is returned by the self executed function, so, it is similar to:
var ray = undefined;
Now the statement 'ray.speak()' is same as executing 'undefined.speak()', which would throw an error, obviously.
Also, executing obj.speak is same as executing 'undefined.speak()', because the variable 'obj' is only available inside that self executing function. Outside the function, 'obj' is not defined.
Hope this helps. :)
Edit:
Explanation for your question about the return statement:
The return statement returns whatever is the output of the code/statement in front of it.
Examples:
var a = 2;
return a; // will return a's value, i.e. '2'
var obj = { x:1 };
return obj; // will return the obj variable's value i.e. { x:1 }
var a = 1;
return a > 1; // will return false i.e. what 'a > 1' outputs after execution
so if you write
return obj = { x:1 };
this will return what the assignment 'obj = { x:1 }' outputs, which is obj's assigned value.
Now coming to your code
var ray = (function(){
return obj = {
speak: function (){
console.log("Haseeb");
}
}
})();
Here the return statement doesn't make obj available to the scope outside the function, it just returns the value of obj, which is then assigned to 'ray'.
The reason that you are able to do obj.speak() without getting any exceptions is that you have used the variable obj without declaring it inside the function using 'var' keyword, which results in 'obj' getting automatically declared in the global scope. And that is why you are able to access 'obj' outside of the function too.
If you change your code to this:
var ray = (function(){
var obj;
return obj = {
speak: function (){
console.log("Haseeb");
}
}
})();
You will get exception while trying to execute obj.speak() outside the function. Because 'obj' is now declared and available only inside the function.
I would suggest reading some more tutorials about variable scope in JavaScript and playing around a bit on the console. :)
Hope this helps :)
Related
I have a function that returns a variable and a function which edit the variable value.
But it's not working and I don't know why.
And what is the correct way to do this?
Here is my code:
function t(){
var test = 1;
var changeTest = function(){
test++;
}
return {
changeTest:changeTest,
test:test
}
}
var b = t();
b.changeTest();
console.log(b.test) // the value is 1 not 2
The value of test is a primitive and so it is indeed not a reference.
A solution: make the exposed test property a getter, so that the value of the private test variable is retrieved at the moment the property is accessed:
return {
changeTest:changeTest,
get test() { return test }
}
function t(){
var test = 1;
var changeTest = function(){
test++;
}
return {
changeTest,
get test() { return test }
}
}
var b = t();
b.changeTest();
console.log(b.test);
With this pattern, the test variable remains private, and you only expose the features you want to. So in this case you allow explicitly to read the test value, but not to write it.
NB: you can shorten the object literal notation to just:
return {
changeTest,
get test() { return test }
}
In changeTest you have to use this.test instead of test.
function t(){
var test = 1;
var changeTest = function(){
this.test++;
}
return {
changeTest:changeTest,
test:test
}
}
var b = t();
b.changeTest();
console.log(b.test) // the value is 1 not 2
If you would like to increase inside of the function, you need to use this keyword inside, just like the following:
function t(){
const changeTest = function() { this.test++; };
return { changeTest, test: 1 };
}
const b = t();
console.log('original value', b.test);
b.changeTest();
console.log('increased value', b.test);
The reason is why it is happening because you are not modifying the value inside, it is called lexical closure what you face with, as the documentations states:
A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function’s scope from an inner function. In JavaScript, closures are created every time a function is created, at function creation time.
Using the this keyword the code accesses the proper test variable.
For further explanation please read further here:
Closures: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
this: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
I hope this helps!
I want to know how the function has been initialized, with the expression or declaried as fuction. _ Amazon interview question
expression : var a = function (){ }
declaration: function a (){ }
You could just do a.toString() and parse out the name. Or do the same with regular expressions
a.toString().test(/^\s*function\s*\(/);
function a(){ }; // gives false
var a = function (){ }; // gives true
Of course as Grundy pointed out this fails with named functions. Something like
var a = function b() {};
or
function b() {};
var a = b;
And ES6 has .name (see the Browser table at the bottom for the current state of affairs) - https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Function/name
I don't think it's possible to do so. The only difference between:
var func = function(){ };
and:
function func() { };
Is that the first one gets assigned on runtime. The way I see it, is that both function statements return a reference to their respective function objects. In that sense they are both the same. The only thing you could argue is that one is not named and the other one is, but you could have assigned a named function to a variable too.
However, there seems to be a difference on how they get assigned. The second one seems to get assigned to a variable that its named after, right at the start of the execution context. The first one has to wait for the explicit assignment within the execution context.
So you'd be testing for when they get assigned. You might think that's is possible to do so within the global object like:
//some protected vars that can't work without same-origin
var protected = ['caches', 'localStorage', 'sessionStorage', 'frameElement'];
var definedAtInit = [];
for(prop in window){
if(!isSandboxed(prop) && typeof window[prop] === 'function'){
definedAtInit.push(prop);
}
};
function isSandboxed(prop){
return protected.indexOf(prop) !== -1;
}
function isItDefinedAtInit(funcName){
return definedAtInit.indexOf(funcName) !== -1;
}
var func = function() {
console.log('test');
}
var results = { isItDefinedAtInit : isItDefinedAtInit('isItDefinedAtInit'),
func : isItDefinedAtInit('func')
};
document.getElementById('results').innerHTML = JSON.stringify(results, '/t');
<pre id="results"></pre>
However, you could still do something like:
var isItDefinedAtInit = function() { };
//After this, isItDefinedAtInit('isItDefinedAtInit') would be wrong.
And you still have the problems with other execution contexts, I don't think functions declared within a function execution context get attached to any object.
I think these kind of checks are a bad idea to be honest.
There is only way, we can determine function has defined with function declarations not as expression.
as Grundy mentioned name property of the respective function gives require information, if it has been defined with expression name property holds undefined value, else it holds function name.
Here is the code :
var isDefinedAsFunction = function(fn){
return fn.name !== undefined
}
Hey guys am a bit confused in running a function from the other. What I have tried is:
var a = (function() {
var babe = function() {
console.log('yay');
};
})();
When I run the code like a.babe() it gives me error like TypeError: Cannot read property 'babe' of undefined. Why is it happening like this?
I want to call the function babe from a ... How can i do it?
I hope you guys can help me ...
Thanks in advance.
You are creating a function called babe and it stays only within the scope of the immediately invoked function expression (IIFE) surrounding it. And since you are not returning anything to the caller, by default, the function call will be evaluated to undefined and that will be stored in a. That is why you are getting the error,
TypeError: Cannot read property 'babe' of undefined
It means that, you are trying to access a property called babe on an undefined value. In this case, a is undefined.
Instead of all this, you can simply return the babe function from the IIFE, wrapped in an object, like this
var a = (function() {
return {
babe: function() {
console.log('yay');
}
};
})()
Now, that the returned object is assigned to a, you can invoke babe function like this
a.babe();
babe is a local variable to the IIFE in that code. It isn't returned. It isn't a property of anything. It isn't accessible.
You have to expose it publicly if you want it to call it from outside that function.
var a = (function() {
var babe = function() {
console.log('yay');
}
return babe;
})();
a();
var a = (function() {
var babe = function() {
console.log('yay');
}
return {
"babe": babe
};
})();
a.babe();
Why have you made a a self executing function? What you want to do is to make a function babe part of an Object a for that, simply do this:
var a = {
babe: function() {document.write('yay');}
}
a.babe();
I have made an object a and added a function babe inside it.. then used the dot notation to access the function inside object a
To use your code you must do
var a = (function() {
var babe = function() { console.log('yay'); }
return babe
})();
a();
To make it a.babe() look at #thefourtheye or #Quentin.
The dot syntax is used to access a "property" of an object. So, in a simple example, you could use something like:
var a = {
babe: function(){ console.log('yay') }
};
a.babe(); // yay
In the case of your example, if you want to create a closure to hide other variables and functions from the global scope, you have to return an object that will then get assigned to a:
var a = (function() {
return {
babe: function(){ console.log('yay') }
}
})();
a.babe(); // yay
Just remember, anytime you use a dot, the variable in front HAS to be an object.
A JavaScript newbie here. I have this following code:
function testObject(elem) {
this.test = "hi";
this.val = elem;
console.log(this.test+this.val);
echo();
function echo () {
console.log(this.test+this.val);
}
}
var obj = new testObject("hello");
When it is run, I expect "hihello" to be outputted twice in the console. Instead it outputs as expected the first time but returns NaN the second time.
I'm sure I'm missing something here. I thought that the internal function can access the vars held outside. Can someone please guide me? I'm more of a functional UI developer and don't have much experience with OO code.
Thanks!
The problem is that inside echo the this value points to the global object, and this.test and this.val (which are referring to window.test and window.val) are undefined.
You can set the this value of echo by invoking it like:
echo.call(this);
That happens because you were invoking the function by echo();, then the this value is implicitly set to the global object.
Give a look to this question to learn how the this value works.
Edit: For being able to calling just echo(); you should persist the this value from the outer function context, there are a lot of ways to do it, for example:
//...
var instance = this; // save the outer `this` value
function echo (){
console.log(instance.test+instance.val); // use it
}
echo();
//...
Or
//...
var echo = (function (instance) {
return function () {
console.log(instance.test+instance.val);
};
})(this); // pass the outer `this` value
echo();
//...
You could also do this:
function testObject(elem) {
this.test = "hi";
this.val = elem;
console.log(this.test+this.val);
this.echo = function () {
console.log(this.test+this.val);
}
this.echo();
}
var obj = new testObject("hello");
​Whenever you call this.echo() or obj.echo(), this will be bound to the object invoking the function.
Personally, I find it elegant to declare class methods like this:
function testObject(elem) {
this.test = "hi";
this.val = elem;
this.echo();
}
testObject.prototype = {
echo: function () {
console.log(this.test + this.val);
}
}
var obj = new testObject("hello");
Are the JavaScript code snippets given below some sort of function declaration? If not can someone please give an overview of what they are?
some_func = function(value) {
// some code here
}
and
show:function(value){
// some code here
}
There are six ways/contexts in which to create functions:
1) Standard declarative notation (most familiar to people with C background)
function foo() {}
All the rest are function expressions:
2) As a method of an object literal
var obj = {
foo: function() {}
};
3) As a method of an instantiated object (created each time new is exectued)
var Obj = function() {
this.foo = function() {};
};
4) As a method of a prototype (created only once, regardless of how many times new is executed)
var Obj = function() {};
Obj.prototype.foo = function() {};
5) As an anonymous function with a reference (same effect as #1) *
var foo = function() {};
6) As an immediately executed anonymous function (completely anonymous)
(function() {})();
* When I look at this statement, I consider the result. As such, I don't really consider these as anonymous, because a reference is immediately created to the function and is therefore no longer anonymous. But it's all the same to most people.
The first one is simply creating an anonymous function and assigning it to a variable some_func. So using some_func() will call the function.
The second one should be part of an object notation
var obj = {
show:function(value){
// some code here
}
};
So, obj.show() will call the function
In both cases, you are creating an anonymous function. But in the first case, you are simply assigning it to a variable. Whereas in the second case you are assigning it as a member of an object (possibly among many others).
First is local (or global) variable with assigned anonymous function.
var some_name = function(val) {};
some_name(42);
Second is property of some object (or function with label in front of it) with assigned anonymous function.
var obj = {
show: function(val) {},
// ...
};
obj.show(42);
Functions are first-class citizens in JavaScript, so you could assign them to variables and call those functions from variable.
You can even declare function with other name than variable which that function will be assigned to. It is handy when you want to define recursive methods, for example instead of this:
var obj = {
show: function(val) {
if (val > 0) { this.show(val-1); }
print(val);
}
};
you could write:
var obj = {
show: function f(val) {
if (val > 0) { f(val-1); }
print(val);
}
};
One way of doing it:
var some_func = function(value) {
// some code here
}
Another way:
function some_funct() {
}
Yet another way:
var some_object={};
some_object["some_func"] = function() {};
or:
var some_object={};
some_object.some_func = function() {};
In other words, they are many ways to declare a function in JS.
Your second example is not correct.
The first one is a function declaration assigned to a variable (at least it should be, despite the fact that it's missing the variable type declaration first), the second one is probably related to a object declaration.
They are called anonymous functions; you can read more about them here:
http://www.ejball.com/EdAtWork/2005/03/28/JavaScriptAnonymousFunctions.aspx
The first example creates a global variable (if a local variable of that name doesn't already exist) called some_func, and assigns a function to it, so that some_func() may be invoked.
The second example is a function declaration inside an object. it assigns a function as the value of the show property of an object:
var myObj = {
propString: "abc",
propFunction: function() { alert('test'); }
};
myObj.propFunction();
The first one...
some_func = function(value) {
// some code here
}
is declaring a variable and assigned an anonymous function to it, which is equivalent to...
function some_func (value) {
// some code here
}
The second one should look like this...
obj = {
show:function(value){
// some code here
}
}
// obj.show(value)
and equivalent to...
//pseudo code
class MyClass {
function show (value) {
// some code here
}
}
obj = new MyClass(); // obj.show(value)
Cheers