I am not sure how to solve this issue. Lets assume we have two functions like this:
JSLint will complain that rebind_test2(); is not defined before it is accessed. And if I move rebind_test2() above the first function, it will complain again that rebind_test1(); is not defined before its accessed. Is there a solution to this?
function rebind_test1(){
"use strict";
$('#row').load('test/', function(result){
rebind_test2();
});
}
function rebind_test2(){
"use strict";
var i = 1;
rebind_test1();
}
var rebind_test2;
function rebind_test1(){
"use strict";
$('#row').load('test/', function(result){
rebind_test2();
});
}
rebind_test2=function(){
"use strict";
var i = 1;
rebind_test1();
}
#torazaburo's answer will work, and alternatively you can just pretend that the function declared second is "global" (as if it was declared in a different file):
/*global rebind_test2 */
Related
this is a curiosity type of question.
Assuming a file library.js as follows:
function alpha(){
console.log("in alpha");
beta();
console.log("back in alpha");
}
function beta(){
console.log("in beta")
}
module.exports = {
alpha:alpha
}
When this library is required from another file say main.js then calling the alpha function from this module will look as follows:
var lib = require("library.js")
lib.alpha();
//outputs:
//in alpha
//in beta
//back in alpha
However the beta() function is not really exported. Does this mean NodeJS looks in the library.js file for beta()? If anyone could explain the process in technical detail it would be great.
It depends on the Scope of the function, you can always call functions or variables from the same Scope or all surrounding Scope.
A Scope is usually a function-Statement and it is surrounded by maybe the global Scope (in Browsers the global Scope is window). You can nest functions and the inner functions have access to their own variables as well as the variables of their surrounding Scopes. Take a look at this example:
var varInGlobalScope = 'global'; // This is always accessible
var functionInGlobalNamespace = function () {
// This is accessible inside the function 'functionInGlobalNamespace'
// and all nested functions but not from the global Scope
var varInFunction = 'in function';
var functionInFunction = function () {
// This is accessible inside the function 'functionInFunction'
// but not from 'functionInGlobalNamespace' or the global Scope
var varInFunctionInFunction = 'in function in function';
console.log(varInFunctionInFunction); // works
console.log(varInFunction); // works
console.log(varInGlobalScope); // works
}
console.log(varInFunctionInFunction); // fails
console.log(varInFunction); // works
console.log(varInGlobalScope); // works
}
console.log(varInFunctionInFunction); // fails
console.log(varInFunction); // fails
console.log(varInGlobalScope); // works
This Scope is always there, this means if you build a function as a public member of another function and call a private Member from that it works. But if you are not in the correct Scope it fails. This behaviour is important if you extend the prototypes of an object.
var Demo = function () {
var privateFunction = function () {
console.log('private');
};
this.publicMethod = function () {
console.log('public');
};
this.publicMethodToCallPrivateFunction = function () {
privateFunction();
};
}
Demo.prototype.tryCallingPublicMethod = function () {
this.publicMethod();
};
Demo.prototype.tryCallingPrivateFunction = function () {
privateFunction();
};
var demo = new Demo();
demo.publicMethod(); // works
demo.publicMethodToCallPrivateFunction(); // works
demo.tryCallingPublicMethod(); // works
demo.tryCallingPrivateFunction(); // fails
And now comes the "magic"-part of Node.js because if you build a module to require it in another module or file you have to put all exportable things into the special object module.exports. This is basically a object which is returned by the require function, but as we learned in the examples before the whole Scope of this function is still there.
There are a few other aspects which are maybe important in this handling, but to explain these will bloat the answer.
As a tip you can use this perfectly to implement private functionality and only provide a clean interface to the user. For example to split a huge function into several small chunks to maintain a clean code base.
The reason why this works it because of closure and hoisting.
First of all nodejs creates a surrounding block around the content of a file that looks like this:
(function (exports, require, module, __filename, __dirname) {
function alpha(){
console.log("in alpha");
beta();
console.log("back in alpha");
}
function beta(){
console.log("in beta")
}
module.exports = {
alpha:alpha
}
});
Function declarations are always parsed before the code execution and always hoisted to top. So they are known by each other.
A function Definition like this:
function beta(){
console.log("in beta")
}
can be seen as a shorthand for this:
var beta = function beta(){
console.log("in beta")
}
With the difference that both the declaration and the definition of the function are hoisting to the beginning of the scope.
The resulting code will look this way:
(function (exports, require, module, __filename, __dirname) {
var alpha, beta;
alpha = function alpha(){
console.log("in alpha");
beta();
console.log("back in alpha");
}
beta = function beta(){
console.log("in beta")
}
module.exports = {
alpha:alpha
}
});
Functions which are not exported in the module, works as private method that can not be called from outside. They may only be used if some other function exported use it, else will be inaccessible code.
I am having a "Possible strict violation" warning from JSHint about the use of this keyword. The OP of this question faced a similar issue (mentioned in the update), but I don't think anyone addressed the reason of it. My code is of the form:
foo.prototype = (function (){
"use strict";
function bar (barfoo) {
if(this.foobar === 0)
{
//do something
}
}
})();
In this case, JSHint complains about the use of this keyword ("Possible strict violation"). However, the warning goes away if I change it to:
foo.prototype = (function (){
"use strict";
var bar = function (barfoo) {
if(this.foobar === 0)
{
//do something
}
}
})();
What is the reasoning behind this? I'd like to understand the reason instead of just using a function expression or /* jshint validthis: true */ to suppress it.
Thanks!
I am trying to work out a style of javascript modular coding.
Currently I have a "mount variable" declared in a global.js that is linked to all the pages in a web application. It contains global site stuff, like javascript language switching:
var app = window.app || {};
app.Lang = (function ($) {
"use strict";
var init = function () {
...
};
};
return { init: init };
})($);
app.GlobalLogic = (function ($) {
"use strict";
var ready = $(function () {
app.Lang.init();
});
}($));
As you can see, I am using immediately executed functions to initialize the logic for a loaded code in the file.
Now I am trying to write an isolated javascript file that can have a similar variable names with other files loaded on the same page. Here is an example:
app.GalleriesAdminLogic = (function ($) {
"use strict";
var MountDivID = "#galleries-management-view";
...
var constructorFunction = function () {
var initialDataObject = $.parseJSON($(MountDivID + " #initial-galleries-list").val());
...
}($));
Notice the variable MountDivID. If there was a similar js file loaded at the same time, that would also contain a definition for variable named MountDivID, would it create a resolution conflict? What is the correct pattern to address a same name variables only from local function?
Variables declared inside functions are local to that function. They are not visible to other functions, and they "hide" variables with the same name declared outside the function.
Let's say we have this script.
var apple = {
type: "macintosh",
color: "red",
getInfo: function () {
return this.color + ' ' + this.type + ' apple';
}
///more functions here....
}
How can I let all these functions run in strict mode? I can put "use strict" at the top of the file but JSlint does not approve this. An alternative is to put "use strict" in every function, but is there a better option?
Wrap everything inside an IIFE and JSLint should approve.
(function () {
"use strict";
//all your code here
}());
Note that variables/functions previously declared in the global scope would no longer be accessible in the global scope when moved to inside this immediately-invoked function expression.
You will have to explicitly set these as properties of the global object, e.g. the window object for browser environment:
(function () {
"use strict";
window.someGlobalVariable = "something";
}());
#zzzzBov's solution also works nicely on both browser and back-end environments.
Wrap everything in an IIFE, alias the global reference, and explicitly set global variables on the global object:
(function (root) { //could be window (browser), could be global (node)
"use strict";
...code...
root.apple = apple; //explicitly make apple a global variable
}(this));
If you are using namespaces for your object literals, I like this approach best:
(function (myApp) {
'use strict';
myApp.myObj = {
init: function(){}
}
}(window.myApp = window.myApp || {}));
myApp.myObj.init();
I've wrapped all my functions around an immediately-invoked function expression as shown:
(function(){
"use strict";
function toggleComment(parentCommentID) {
$("form#" + parentCommentID).toggle();
}
function scrollBottom() {
window.scrollTo(0, document.body.scrollHeight);
}
})();
However, upon calling one of these functions through a link:
Reply
The Chrome console outputs Uncaught ReferenceError: toggleComment is not defined. Am I mistaken in thinking that an immediately-invoked function expression, as its name suggests, should be invoked immediately and therefore toggleComment should be called? Should I call the function differently?
The function toggleComment is not visible. It's enclosed in the ready function you're using; if you want to be able to call it like that (which is not recommended, in most cases), you have to hoist it outside of that function and make it globally accessible.
And this has nothing to do with strict. If you remove the strict line, this problem will still be the same.
The functions are no longer declared in the global scope. Try
window.toggleComment = function(parentCommentID) {
$("form#" + parentCommentID).toggle();
};
You have declared the functions inside a closure. They're outside of the scope of the HTML tag.
You could set an id to your <a> tag as well as publish your function to the global scope, so you can do this:
(function(){
"use strict";
var toggleComment = function(parentCommentID) {
$("form#" + parentCommentID).toggle();
}
function scrollBottom() {
window.scrollTo(0, document.body.scrollHeight);
}
document.getElementById("yourATagId").onclick(function() {
toggleComment(159);
});
window.toggleComment = toggleComment;
})();
Maybe you could benefit from this simple singleton pattern:
(function() {
var controller = {};
controller = new function() {
this.sampleProperty = "my property";
}
controller.yourFunction = function() {
var localVariable;
console.log("I can access " + this.property);
};
window.controller = controller;
})();
This way, controller will be known to your global scope.