'use strict' var foo = 'foo'; var wow = 'wow'; function bar (wow) { var pow = 'pow'; console.log(foo); // 'foo' console.log(wow); // 'zoom' } bar('zoom'); console.log(pow); // ReferenceError: pow is not defined
'use strict' // var foo; var wow; // , , function bar (wow) { var pow; pow = 'pow'; console.log(foo); console.log(wow); } foo = 'foo'; wow = 'wow'; bar('zoom'); console.log(pow); // ReferenceError: pow is not defined
pow
was declared in the bar
function, since this is its scope. Note that the variable is not declared in the parent, with respect to the function, scope.wow
parameter of the bar
function is also declared in the function scope. In fact, all the parameters of the function are implicitly declared in its scope, and that is why the console.log(wow)
command in the ninth line, inside the function, displays the zoom
instead of wow
.eval
or with
commands. We believe that these commands, in any case, should not be used.bar()
call is performed in line 12.bar
before making this call, it does it, starting with the search in the current scope. At that moment, the current is the global scope. Thanks to the first pass, i.e. compilation, we know that the bar
declaration is at the top of the code, so the interpreter can find it and perform the function.console.log(foo);
command console.log(foo);
, the interpreter, before executing this command, will need to find the declaration foo
. The first thing he does, again, is looking for the current scope, which at this moment is the scope of the function bar
, and not the global scope. Is the variable foo
declared in the function scope? No, it is not. It then goes up a level, to the parent scope, and looks for a variable declaration there. The scope in which the function is declared is the global scope. Is the variable foo declared in the global scope? Yes it is. Therefore, the interpreter can take the value of a variable and execute the command.ReferenceError
error.foo
declared in the current scope of the function will shade or hide the variable with the same name declared in the parent scope. Take a look at the following example in order to better understand this idea: 'use strict' var foo = 'foo'; function bar () { var foo = 'bar'; console.log(foo); } bar();
bar
in the console, not foo
, since declaring the variable foo
in the sixth line will block the declaration of the variable with the same name in the third line. 'use strict' function convert (amount) { var _conversionRate = 2; // return amount * _conversionRate; } console.log(convert(5)); console.log(_conversionRate); // ReferenceError: _conversionRate is not defined
catch
expression in the try / catch
construct has a block scope, which means that this expression has its own scope. It is important to note that the try
expression does not have a block scope, only the catch
expression has it. Consider an example: 'use strict' try { var foo = 'foo'; console.log(bar); } catch (err) { console.log('In catch block'); console.log(err); } console.log(foo); console.log(err);
bar
, which causes the interpreter to go to the catch
expression. In the scope of the expression declared variable err
, which will not be accessible from the outside. In fact, the error will be displayed when we try to output the value of the variable err
to the log in the line console.log(err)
This is what this code will output: In catch block ReferenceError: bar is not defined (...Error stack here...) foo ReferenceError: err is not defined (...Error stack here...)
foo
is available outside the try / catch
construct, and err
is not.let
and const
keywords, variables and constants implicitly join the current block scope instead of the functional scope. This means that these constructs are limited to the block in which they are used, whether it be an if
block, a for
block, or a function. Here is an example that will help to better understand this: 'use strict' let condition = true; function bar () { if (condition) { var firstName = 'John'; // let lastName = 'Doe'; // if const fullName = firstName + ' ' + lastName; // if } console.log(firstName); // John console.log(lastName); // ReferenceError console.log(fullName); // ReferenceError } bar();
let
and const
keywords allow us to use the principle of least disclosure. Following this principle means that the variable must be available in the smallest possible scope. Prior to ES6, developers often achieved a blocky scope effect using the stylistic method of declaring variables with the var
keyword in an instantly executed functional expression (Immediately Invoked Function Expression, IIFE), but now, thanks to let
and const
, you can apply a functional approach. Some of the main advantages of this principle are to avoid unwanted access to variables, and thus reduce the likelihood of errors. In addition, it allows the garbage collector to free memory from unnecessary variables when leaving the block scope. 'use strict' var foo = 'foo'; (function bar () { console.log('in function bar'); })() console.log(foo);
in function bar
before the output of foo
, since the bar
function is executed immediately, without the need to explicitly call it using a bar()
. This happens for the following reasons: 'use strict' for (var i = 0; i < 5; i++) { setTimeout(function () { console.log('index: ' + i); }, 1000); }
for
loop, in which the asynchronous setTimeout
operation is called, will look like this: index: 5 index: 5 index: 5 index: 5 index: 5
for
loop will end and counter i
will be equal to 5. 'use strict' for (var i = 0; i < 5; i++) { (function logIndex(index) { setTimeout(function () { console.log('index: ' + index); }, 1000); })(i) }
i
to IIFE. A functional expression will have its own scope, which is no longer affected by what happens in the for
loop. This is what this code will output: index: 0 index: 1 index: 2 index: 3 index: 4
Source: https://habr.com/ru/post/337038/
All Articles