Does a statement with only a variable name do something in JavaScript? - javascript

In this example:
someVariable;
does the code do anything? More technically, is there some work associated with it from the point of view of a JS engine like V8?
I'm asking because I'm looking to temporarily suppress the "variable is declared but its value is never read" warning by TypeScript and I'm doing this:
function xyz(arg) {
arg;
// ...
}
Is there a better "no-op" construct in JavaScript?

One thing it does is it checks to see if the variable is defined, If it isn't, it'll throw an error.
If you're worried about side-effects, if you happen to be inside a with statement, it can invoke a getter and run code, but this is unlikely. If the variable name in question isn't local and happens to be a getter on window, it can also run code, eg
Object.defineProperty(window, 'foo', { get() {
console.log('getting');
}});
console.log('start');
foo;
But this, too, is pretty unlikely.
If you're sure the variable referred to is a normal variable in scope, it won't do anything - it'll just be an unused expression.

Beside the checking of the exisiting of the variable, it perfoms an evaluation of the expression.
var foo = {
get bar() {
console.log('get bar');
return 42;
}
};
foo.bar;

Related

Difference between IIFE and regular function (example)

Learning about IIFEs i understand that using them does:
not pollute the global scope
shields your code from others.
Could someone please help me understand it better and give a real example of when i could get in trouble when using regular function statement (instead od IIFE?)
Let's say you have a decent sized codebase (a few thousand lines or more). Putting every function on the top level won't be a good idea, because then it'll be pretty easy to accidentally write a function name twice, which will cause bugs due to the name collision. For example:
// code around validating user registration
function validate(username) {
return /someValidationRegex/.test(username);
}
// do stuff with validate
// And then, far elsewhere in the code,
// you need to validate an input for sending to the server:
function validate(input) {
return /someOtherValidationRegex/.test(input);
}
// do stuff with validate
This will not work, because the last validate function will overwrite the first validate function, and the code won't work as expected.
Put each segment of code into an IIFE instead, to avoid the possibility of name collisions:
(() => {
// code around validating user registration
function validate(username) {
return /someValidationRegex/.test(username);
}
// do stuff with validate
})();
(() => {
// code around validating an input for sending to the server:
function validate(input) {
return /someOtherValidationRegex/.test(input);
}
// do stuff with validate
})();
This is the technique that Stack Overflow's Javascript uses (at least in some parts).
Another reason to use IIFEs even if you're careful not to duplicate function names is that you may accidentally duplicate a window property. For example, the following is a somewhat common bug people run into:
// name is defined to be a number...
var name = 5;
// but it's actually a string???
console.log(typeof name);
The problem here is that you're accidentally referring to / overwriting the window.name property on the top level, and window.name may only be a string. There are a whole bunch of functions and variables defined on the top level. To avoid name collisions, put everything into an IIFE instead:
(() => {
// name is defined to be a number...
var name = 5;
// And it's still a number, good
console.log(typeof name);
})();
Still, if your codebase is large enough that name collisions are a decent possibility, rather than manually writing IIFEs, I'd highly recommend using a module system instead, like with Webpack. This will allow you to write modules inside their own encapsulated scope, without leakage or name collisions, and will be more maintainable, when each module only contains exactly the code it needs to run, and nothing more. This makes identifying bugs and extending features much easier than one huge long <script> that you have to navigate through manually.
The common advantage of IIFE is that any "Function or Variable" defined inside IIFE, cannot be accessed outside the IIFE block, thus preventing global scope from getting polluted.
IIFE's are used to define and execute functions on fly and use them on the spot without extra line of Code.
(function(){
var firstName = 'Jhon';
console.log(firstName);
})(); // will be executed on the fly
function test(){
var firstName = 'Jhon';
console.log(firstName);
}
test(); // has to call manually
The IIFE will actually run (immediately-invoked function expression), they don't need a trigger or function call to initiate them, so the variable will be set to its response.
Here's a Fiddle to demonstrate this:
var iffe = (function() {
return 'foo';
})();
var func = function() {
return 'bar';
};
console.log('iife = ' + iffe);
console.log('non-iife = ' + func);
In your JS console you'll see something similar to:
iife = foo and
non-iife = function () {
return 'bar'; }
Also in case we need to pass something in the IFFE scope from the outer scope we need to pass them as a parameter and receive this inside the function defined in the IFFE wrap, something like this -:
var iffe = (function(doc) {
return 'foo';
})(document);
This is a link for some more reference - http://benalman.com/news/2010/11/immediately-invoked-function-expression/

When to use an anonymous function in Nodejs?

Recently I was debugging a bit of code that one of my coworkers wrote and found something along the lines of this within a conditional, inside of a larger function.
(function(foo){
...
console.log(foo);
...
})();
So it looks like this very boiled down
function display(db, user, foo) {
if (isValid(db, user) {
(function(foo){
console.log(foo);
})();
}
...
}
Originally it didn't have (); at the end so to my understanding it wasn't even being called but to my broader question, what's the difference between that and something like below? I've seen this syntax a few times but I don't understand how above would be useful for this purpose. My understanding would reason that this just adds unnecessary complexity. Someone please enlighten me!
function display(db, user, foo) {
if (isValid(db, user) {
// without abstract function
console.log(foo);
}
...
}
Thanks :-)
With such a simple example, there is no reason to use an anonymous function like this in node.js or any other JavaScript environment when the inner function could be called directly instead.
When conducting reviews, I often will assume that any console.log (or choose-your-language logging) is accidental. If the surrounding source doesn't do anything of value itself, it is likely only intended to support a (possibly-out-of-date) console.log during development and debugging.
Because JavaScript is single-threaded, constructing an anonymous function of this sort is strictly for scoping. In the case of the original source that didn't have the execution (i.e. it was missing the ()), this is actually a way to "hide" debug code from the runtime while leaving it in-place if a step-through debug ever needed it.
When debugging, it's as easy as adding the ('isValid succeeded') to have it execute all the source inside.
(function(foo){
console.log(foo);
})( /* You're missing a parameter value here; will print 'undefined'. */ );
Sometimes you use an anonymous function to limit the scope of your code. It may come handy if you do not want to pollute the global scope with your variables. Also, it makes dependency injection for testing easier.
Consider the following examples:
var a = 2, b = 3;
function print(x)
{
console.log('x= ', x);
}
print(a+b);
In the above example, the a, b, and print now belongs to the window object. When your code grows it becomes difficult to keep track and avoid of name collisions. The problem becomes even more severe if you are using 3rd party libs etc.
In the example below, your code is wrapped in an anonymous function protecting the global scope. You can also pass parameters to the anonymous function
(function(localParam){
var a = 2, b = 3;
function print(x)
{
console.log('x= ', x);
}
print(a+b);
//also
console.log(localParam); // = safe way to access and global variables
})(globalParam);

Where are JavaScript constants stored in browser?

I want to be able to take a string and use that to retrieve the value of a constant that has that string's name. In particular, the constant will equal an arrow function.
const foo = (bar) => { return bar }
I expected that it would show up in the window object, but it doesn't:
let fn = window['foo'] // undefined
Right now, the only way I can figure out how to do this is to use the older function syntax:
function foo(bar) { return bar }
let fn = window['foo'] // function foo(bar) { return bar }
Is there a way I can get the function from the string of its name, when the function is stored within a constant?
Edit:
I feel the need to clarify why I would want to start defining functions like this, as most responses have seemed to find the distinction important. It essentially comes down to scope and mutability.
The way arrow functions handle the this keyword is a little easier to grok with arrow functions and I believe should be the standard behavior unless the old behavior is explicitly required.
Second, the way mutability works with JavaScript, I think that defining functions as constants is a bit safer. Example:
function foo(bar) { return bar }
// Elsewhere
let foo = 4;
// Back at the ranch
foo("return this string please") // foo is not a function.
Ultimately, I think this just reduces mutability, and also causes fewer surprises when using this.
Only global variables get assigned a matching property on the global object. Nothing else, including constants, does.
The value of a constant won't automatically appear anywhere except in the constant itself.
If you want to access it via a string, then store it as a property of an object (preferably not the global object though, that's a disorganised mess with a significant risk of clashing with other code).

Understanding javascript hoisting and execution context

b();
console.log(a);
var a = 'Hello World';
function b(){
console.log('Called b!');
}
I have read about the term "hoisting", but it isn't pretty clear to me. Why does the function gets executed while the variable is set to undefined?
The interesting part is, the variable didn't show any error. But it showed undefined. But when I remove the variable totally, then it shows an error. That means, the variable is present somewhere though. right?
But if it is present, then why can't the compiler compile it and can compile the function here?
I know that var a is getting hoisted. I want to know why the engine is treating the variable and the function in a different way that is what's happening behind the scenes during the execution context.
Any detailed explanation would be helpful about how the engine is creating the execution context.
In this question I'm asking about how javascript engine is behaving differently with the function and the variable. And what is exactly happening in the creating state and execution state of the execution phase. So, it's not a duplicate question.
But if it is present, then why can't the compiler compile it and can compile the function here?
Basically it boils down to whether the value of the binding can be determined without executing the code or not.
The function declaration itself doesn't depend on runtime information. Keep in mind that the body is not evaluated until the function is called. So even without really executing the code, its clear that the value of b is a function.
However, the initialization value of a variable declaration may depend on runtime information. Consider this:
var a = 10 + bar();
There is no way for the engine to "hoist" the initialization value without evaluating the expression (and executing bar in the process).
Of course in your example, the initialization value ('Hello World') is static as well, so it could be hoisted. But then the behavior would be inconsistent and probably more confusing.
What exactly happens when control enters a new function is defined in the spec. There you can see how variable declarations and function declarations are treated.
With hoisting, this is what your code looks like
function b(){
console.log('Called b!');
}
var a;
b();
console.log(a);
a = 'Hello World';
As you can see, a is declared at the the top, but has not been set to a value yet. That is why you get undefined when you log that variable.
If you remove the a variable altogether, you get the Uncaught ReferenceError because a has not been declared.
The above code is same as below
var a;
function b(){
console.log('Called b!');
}
b();
console.log(a);
a = 'Hello World';
Explanation - Function along with its definition are hoisted to the top. Variable declaration is hoisted not its definition
var a; is hoisted. a = 'Hello World!'; is not hoisted. It's that simple.

JavaScript closure, about object and this

function abc(v){
console.log(v);
}
var abcd= abc;
var module = {
name: "hello",
innerFunc: function(){
console.log("name "+name);
},
outterFunc: abc("run from module")
}
Is there a way to in innerFunc to refer the value of name?
My thought is there should be a way, since they are all in the module object. I could be totally wrong.
Please tell me why and why not?
PS:
Actually, I figured out by adding the following code to it
var module = {
name: "hello",
innerFunc: function(){
var self = this;
console.log("name "+self.name);
},
outterFunc: abc("run from module")
}
So, the follow up question is that, why innerFunc is not running like outterFunc, outterFunc is invoked immediate after the running the code, why does innerFunc has to be explicitly called as module.innerFunc().
Thanks
First of all, you don't have to alias this to self to use instance properties. You can just write innerFunc like so:
innerFunc: function(){
console.log("name "+this.name);
},
You've probably seeing var self = this in other code examples, and it is a common way to get around the fact that this changes as you descend into function scopes. It's not a technique I care for...it's usually more clear to use a meaningful variable name. In your case, however, it's not necessary to alias this to self at all.
To answer your second question, it's important to understand the difference between function definition and function invocation.
When you define a function, it is not being executed -- no matter where it's defined. Consider the following example:
function f() {
console.log('f');
}
var o = {
m: function() {
console.log('m');
}
}
In that example, there are two function definitions, but no function invocations. In other words, if you run this script, the function f will exist, and the method o.m will exist, but neither will have been executed, so there will be nothing printed on the command line. In general, if you see the keyword function, you're dealing with a function definition, not an invocation. The following code now invokes both of these functions in turn:
f();
o.m();
In this case, the two calls to console.log will happen.
In your example, you're defining the property outerFunc by invoking the function abc (which I suspect is not what you want to do). How do I know you're invoking it? Because there are parentheses and no function keyword:
var module = {
//...
outterFunc: abc("run from module")
}
What's happening here is abc is getting invoked and its return value is getting assigned to outerFunc. Since abc returns nothing, outerFunc will get the value undefined. Which is why I'm guessing that is not what you want. If you want m.outerFunc to be an alias of abc, you would do that this way:
var module = {
//...
outerFunc: abc
}
Note there are no parentheses...so abc is not invoked. Now module.outerFunc is an alias for abc. Be careful, though! This is a dangerous way to alias functions in JavaScript...in this instance, it's probably okay because you're aliasing a function (not a method), so there's little danger of this not being what you expect, but you'll run into that if you try to alias methods to one another. So in general, this technique should be used with caution.
If you want outerFunc to call abc, you will have to do this:
var module = {
//...
outerFunc: function() {
abc();
}
}
In this case, abc is not being invoked...it is inside a function definition, so it will only be invoked when m.outerFunc is invoked.
I know this can all seem very confusing at first, but these are really important distinctions to understand, so please let me know if this answer isn't clear.

Categories

Resources