I am trying to understand one of the properties of js closures that says :
ref from Closures store references to the outer function’s variables
function myId()
{
var userID=999;
return
{
getId: function() {
return userID;
},
setId: function(newId) {
userID = newId;
}
};
}
var callInnerFun = myId();
console.log(callInnerFun.getId());
callInnerFun.setId(500);
console.log(callInnerFun.getId());
When i try running the above code in Node or even on the browser, i get the following error:
SyntaxError: function statement requires a name at getId: function() {
I have tried and failed to understand what am i really missing out on. Is it some syntactical error, or is it something to do with my text editor, sublime text, because, if i try running the exact same code as copied from the link given above, then things work.
Whereas in my code (above) the logic is still the same as the reference, just the indentation and the variable names have changed. Is it that changing these have broken my code ?
You have two bugs: the first is an extra closing brace before setId. Once you remove that, change:
return
{
to
return {
In Javascript, brace position matters since it inserts a semicolon after the return statement if you don't have one which you don't want. Also I changed the brace position in your myId definition. The final code is:
function myId() {
var userID=999;
return {
getId: function() {
return userID;
},
setId: function(newId) {
userID = newId;
}
};
}
var callInnerFun = myId();
console.log(callInnerFun.getId());
callInnerFun.setId(500);
console.log(callInnerFun.getId());
One '}' is extra here. And also it should be 'return {'
Change the below
getId: function() {
return userID;
}
},
to
getId: function() {
return userID;
},
Hope it helps !!
Related
I am trying to fix a function I have here to be able to use it without using a that = this (or self = this as some like to use). It is a scoping issue but I am not sure how to get around it, and I would like to get in the habit of not using a that = this . So the functions are all in a return (angular factory) and I am having trouble referencing another function . Let me show you what I mean :
return {
loadStates: function() {
var that = this;
//chgeck if is loaded module, then change and fire callback
var currentModules = moduleHolder.getModules();
if (currentModules[name]) {
//works here
this.prepState();
} else {
//module cannot be found check for 5 seconds
$log.warn("Requesting " + name + "...");
var timeToCheck = true;
setTimeout(function() {
timeToCheck = false;
}, 5000);
var check = {
init: function() {
check.checkAgain();
},
checkAgain: function() {
if (timeToCheck) {
if (currentModules[name]) {
//but not here
that.prepState();
} else {
//still doesn't exists
setTimeout(check.checkAgain, 200);
}
} else {
//doesn't exist after 5 seconds
$log.error("Requested module (" + name + ") could not be found at this time.");
}
}
};
check.init();
}
},
prepState: function() {
}
}
So in the top if it finds the currentModule[name] I can use a this.prepState() and it works fine. However inside the timing functions I cannot use the this anything because it is inside a different scope so I have temporarily gotten around this by setting a that = this up top, however I would like see if I could not use this method. How does one get around this without using the that= this? Thanks!
It is a scoping issue...
No, it isn't. this and scope have essentially nothing to do with each other. (For now; ES6's arrow functions will change that.) It's an issue of how the functions are called.
If you pass a function reference to something that will call it later, unless the thing you're passing it to has a way you can use to tell it what to use for this when calling it, your function will get called with this not referring to what you want it to refer to.
You can get a new function reference that will call your original function with the correct this by using Function#bind:
var usesCorrectThis = originalFunction.bind(valueForThis);
So for example, suppose I have:
var check = {
name: "Fred",
sayHello: function() {
console.log("Hi, I'm " + this.name);
}
};
If I do:
check.sayHello();
All is good: Calling the function as part of an expression retrieving it from a property tells the JavaScript engine to use the object as this during the call.
However, if I do:
setTimeout(check.sayHello, 0);
...that doesn't work right, because when setTimeout calls the function, it doesn't use the right value for this.
So I can use Function#bind to address that:
setTimeout(check.sayHello.bind(check), 0);
More (on my blog):
Mythical methods
You must remember this
there are different ways you can do that.
One way is to use bind function.you can use
var checkInitBindFn = check.init.bind(this);
checkInitBindFn();
Secondly you can use call and apply also.
check.init.call(this);
check.init.apply(this);
Like this you can use this instead of that.
Check the complete api doc online...
It's not a scoping issue. If you want to avoid self = this you can always reference functions by objects. Makes cleaner code and since factories in angular are singletons you're not wasting memory.
angular.module('myApp').factory('myFactory', function ($timeout) {
var myFactory = {
loadState: function () {
$timeout(function () {
myFactory.check();
}, 500);
},
check: function () {
},
};
return myFactory;
});
I have this javascript code which is not working.
function myfun()
{
return
{
alert("para");
}
};
myfun();
I have read about the javascript's automatic semicolon insertion. I corrected the above code as
return{
alert("para");
}
But still got the error : unexpected token (.
I wonder why?
NOTE: I don't need the solution but I need the explanation why the above code in not working.
EDIT
According to the book, javascript the good parts, the return statement if returns value must be in same line as return expression.
ie
return {
status: true
};
AND
return
{
status: true
};
Is wrong.Then How come
function myfun(para)
{
var status;
return
{
status : alert(para)
};
};
myfun("ok");
produce no error.It won't work but shows no error as well.It works when the { is in the same line as return.
ie
function myfun(para)
{
var status;
return{
status : alert(para)
};
};
myfun("ok");
In
return {
alert("para");
}
the {...} are interpreted as object literal. An object literal has the form
{
key: value,
//...
}
Object literals cannot contain arbitrary statements.
Looks like you've difficulties with ASI and the difference between run-time and parsing-time.
Where as
return {
status: true
};
is a correct way to return an object, ASI will take an action in the following code:
return
{ // ^-- ASI will insert a semicolon here
status: true
};
The semicolon is automatically inserted, and at run-time all lines after return are ignored. However, at parsing time, everything counts, and if there's a syntax error, like in your first example, an error will be thrown.
The reason why you are getting that error is because JS is expecting a value to the key "para".
There is no compulsion to return in a JavaScript function. If your intention is to test if the control goes to the function, you can simply change it to
function myfun() { alert("para"); }
if you want to return an object with string "para" you should change it to
function myfun() { return { "text": "para" }; }
I am developing a Windows Phone app and using HTML/JS to build it. So there is a WinJS reference in my code.
The following is my code:
WinJS.UI.Pages.define("...", {
ready: function (element, options) {
var item = element.querySelector("#item").winControl;
item.addEventListener("iteminvoked", function (eventInfo) {
eventInfo.detail.itemPromise.done(function itemInvoked(item) {
WinJS.Navigation.navigate("...", { newsItem: item.data });
});
}, false);
}
}
When I ran the code above, it threw the error, saying: 0x800a138a - JavaScript runtime error: Function expected and it lead to base.js, which is part of the WinJS language (correct me if I'm wrong). I used breakpoints and "step over" line-by-line and the line before which the error was thrown is: item.addEventListener....
I tried using http://jshint.com and it didn't show any errors, apart from unused variables and undefined variables (WinJS).
Please let me know if I need to show more code.
When I searched for this problem, I learned that it might be because I added a paranthesis somewhere where I wasn't supposed to, hence it's treating it as a function.
your missing a curly bracket
WinJS.UI.Pages.define("...", {
ready: function (element, options) {
var item = element.querySelector("#item").winControl;
item.addEventListener("iteminvoked", function (eventInfo) {
eventInfo.detail.itemPromise.done(function itemInvoked(item) {
WinJS.Navigation.navigate("...", { newsItem: item.data });
});
}, false);
} // HERE
}
In the Restify framework code I found this function:
function queryParser(options) {
function parseQueryString(req, res, next) {
// Some code goes there
return (next());
}
return (parseQueryString);
}
Why would the author write return (next()); and return (parseQueryString);? Does it need parentheses there and if so, why?
Using parentheses when returning is necessary if you want to write your return statement over several lines.
React.js offers a useful example. In the return statement of the render property in a component you usually want to spread the JSX you return over several lines for readability reasons, e.g.:
render: function() {
return (
<div className="foo">
<h1>Headline</h1>
<MyComponent data={this.state.data} />
</div>
);
}
Without parentheses it results in an error!
More generally, not using parentheses when spreading a return statement over several lines will result in an error. The following example will execute properly:
var foo = function() {
var x = 3;
return (
x
+
1
);
};
console.log(foo());
Whereas the following (without the parentheses) will throw errors:
var foo = function() {
var x = 3;
return
x
+
1
;
};
console.log(foo());
It doesn't need to be that way, but it's valid JavaScript code. Actually it's quite uncommon to see such syntax. I guess it's a personal preference of the author.
Parenthesis are used for two purposes in a return statement.
To support multi-line expression as mentioned in #Andru Answer.
To allow returning object in arrow function like the below:
() => ({ name: 'Amanda' }) // Shorthand to return an object
This is equivalent to
() => {
return { name : 'Amanda' }
}
For more information, please check this article.
https://medium.com/#leannezhang/curly-braces-versus-parenthesis-in-reactjs-4d3ffd33128f
// Create a component named MessageComponent
var MessageComponent = React.createClass({
render: function() {
return (
<div>{this.props.message}</div>
);
}
});
NOTE Why do we need the parentheses around the return statement (line
3)? This is because of JavaScript's automatic semicolon insertion.
Without the parentheses, JavaScript would ignore the following lines
and return without a value. If the JSX starts on the same line as the
return, then parentheses are not needed.
Taken from here.
Just to add to what others have said.
Using brackets around the return value is valid JavaScript, but mostly a bad thing to do.
Mostly bad because it doesn't add anything yet increases the size of the JavaScript which means that there is more to download to the browser. Yes most people have fast broadband connections, but don't lose sight of the fact that everything you put in the JavaScript file needs to be downloaded so avoid unnecessary code bloat. This probably doesn't matter if you use a tool to compact your code (minifier has already been mentioned), but not everyone does.
Sometimes it might aid readability. Hard pressed to think of an example in this case, but if the use of brackets makes your JavaScript clearer to you as the developer and thus easier to maintain then use them - even if it goes against what I said about code bloat.
Why would the author write return (next()); ... ?
Regarding next():
Probably because his function is something like this:
function next()
{
var i=0;
return function (){
// Do something with that closured i....
}
}
Regarding (xxx);:
It is unnecessary. Every minifier will remove it.
Example (uglifyJS):
becomes:
I tried:
var a = function() {
return true || true
}
console.log(a());
//return: true
var a = function() {
return
true || true
}
console.log(a());
//return: undefined
var a = function() {
return (
true || true
)
}
console.log(a());
//return: true
While Andru's answer is popular, it is wrong that parantheses are required for multiline return statement. Here, you can see an object of foo and bar is returned with no parantheses needed.
function foo () {
return {
foo: 'foo',
bar: 'bar',
}
}
console.log(foo())
As long as the return line is not just empty space or linebreak, you can have a multiline return just fine. Otherwise Automatic Semicolon Insertion takeover and break your return statement as demonstrated by Andru.
Regarding your question, I am onboard with Darin's answer.
This may be old but the return () can be used in this way:
function parseQueryString(req, res, next) {
var id = req.param('id');
return (id ? "Foo" : "Bar");
}
Less code, easy to read :)
How to write function(object) with 2 methods (alert and console.log) to be able to use it like this:
fname("text").alert //-now text is alerted;
fname("text").cons //-now text shows in console log.
the methods are not important byt the way of execution. I know that it must be self invoiking function but i cant do it. I dont want to use it this way - fname.alert("text").
Greetings
Kriss
It's not possible in any sane way that works everywhere. The example you posted would require you to define an accessor for those properties - and that only works with modern JS engines.
Anyway, here's code that would actually do this. But please do not use this in any real application! See the last code block for a better solution
function fname(message) {
var obj = {};
Object.defineProperty(obj, 'alert', {
get: function() {
alert(message);
}
});
Object.defineProperty(obj, 'cons', {
get: function() {
console.log(message);
}
});
return obj;
}
This works because fname('hello').alert will cause the getter function for the alert property to be executed - and while such a function should usually return a value there's nothing to stop it from doing something like showing an alert() message.
What you could achieve in a way that works everywhere would be something like that though:
fname('text').alert();
fname('text').cons();
This could be done like this:
function fname(message) {
return {
alert: function() {
alert(message);
},
cons: function() {
console.log(message);
}
}
}
function fname(str) {
return {
alert:function(){alert(str)},
cons:function(){console.log(str)}
}
}
Doing fname("text").alert() alerts text.