Make all functions strict mode literal object? - javascript

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();

Related

Nodejs exporting function that calls non exported function

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.

JSLint: cross reference across functions

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 */

javascript "strict" and instantiating global modules

I'd like to "use strict"; mode in javascript but have some problems with strict warnings.
I have a "widget", e.g.:
var Widget = function () { /* ... */ }
Before I was using it like this (inside a module):
(function () {
var w1 = new Widget();
}());
when I add "use strict"; to this context I get a warning that "Widget" is not defined:
(function () {
"use strict";
var w1 = new Widget(); // <- warning here
}());
What is the proper way of doing this?
Should I define my "widgets" differently?
In strict mode you can't accidentally create global variables. Trying to do so will throw a reference error, as you've noticed. Hence you need to name an object, which has Widget assigned:
window.Widget = function () { /* ... */ }
(function () {
"use strict";
var w1 = new window.Widget();
}());
More info: MDN , www.nczonline.net

Strict mode statement causes functions to be undefined

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.

Function scope in javascript

I thought one of the point of functions in javascript was to provide scope. Things defined in a function were only available inside the function.
function cat(name) {
talk = function() {
alert(" say meeow!" )
}
}
talk()
I would expect the above code to fall over because talk should not be visible. But it is, why?
It is because you didn't declare it with a var keyword.
If you don't use the var keyword, it will be in the global scope. If you do use var, it will be in the function scope:
function cat(name) {
//anonymous function assigned to the local variable talk
var talk = function() {
alert(" say meeow!" )
};
}
You can declare named functions without the var keyword, and they will still be in the local scope:
function cat(name) {
//local talk function
function talk() {
alert(" say meeow!" )
};
}
You haven't actually defined the variable in any scope. So it default to global scope.
function cat(name) {
var talk = function() { // <-- added var
alert(" say meeow!" )
}
}
talk() // fail
JavaScript allows you to use variables without defining them, this makes the programming language easier to learn and more flexible. I wouldn't recommend you make use of this feature though. Always define your variables.
inside of a function, you have to declare variables with "var" or they are declared globally. so you would do:
function cat(name) {
var talk = function() {
alert(" say meeow!" )
}
}
talk() // error: undefined

Categories

Resources