Functional Evaluation Procedure

Using the following code, which is not ES6, and it is not in "strict mode", I expected the result to be "b" because the second declaration of foo should overwrite the first. But the result is "a"!

   {
      function foo() {
        console.log('a');
      }
    }

    function foo() {
      console.log('b');
    }

    foo(); // a  ????? Why not 'b' ????

You would surround this sample code with extra curly braces, then the result would be the expected "b".

{ // additional curly braces 
  {
    function foo() {
      console.log('a');
    }
  }

  function foo() {
    console.log('b');
  }

  foo(); // 'b' as expected !!

}// end additional curly braces 

For an additional illustration, please consider the following additional example:

foo('before declaration'); // outcome :  from outside block :before declaration

{
  function foo(s) {
    console.log('from inside block: ' + s);
  }
}

function foo(s) {
  console.log('from outside block :' + s);
}

foo('after declaration'); // outcome :  from inside block: after declaration

In my decision, the correct result should be

// from outside block :before declaration
// from outside block :after declaration

I cannot find my mistake here.

If I again enclose the complete last example inside curly braces, for example

{
  foo('before declaration'); // outcome :  from outside block :before declaration

  {
    function foo(s) {
      console.log('from inside block: ' + s);
    }
  }

  function foo(s) {
    console.log('from outside block :' + s);
  }

  foo('after declaration'); // outcome :  from outside block: after declaration

}

I will get the expected result.

+4
source share
3 answers

foo() {}, , . w3schools JavaScript,

- JavaScript

, , {}, a.

0

"b" , foo .

, , . "b" , () .

""! "b" ????

( !). - , , - ES5 .

, ? , , . ( ( "" ).

,

var foo₀; // the top-level implicit introduction of the inner declaration
var foo₀ = function foo() { console.log('b'); } // the hoisted declaration
foo()₀; // logs 'b'
{
  let foo₁ = function foo() { console.log('a'); } // the (hoisted) inner declaration
  foo₀ = foo₁; // the weirdness!
  // a call to `foo()` in here would get you foo₁ from the local scope
}
foo()₀; // logs 'a'

var foo₀; // the top-level implicit introduction of the first declaration
var foo₀; // the top-level implicit introduction of the second declaration
{
  let foo₁ = function foo() { console.log('b'); } // the (hoisted) second declaration
  foo()₁; // logs 'b'
  {
    let foo₂ = function foo() { console.log('a'); } // the (hoisted) first declaration
    foo₀ = foo₂; // the weirdness!
    // a call to `foo()` in here would get you foo₂ from the local scope
  }
  foo₀ = foo₁; // the weirdness!
  foo₁() // logs 'b' (as expected) - a call in here does get you foo₁ from the local scope
}
// a call to `foo()` out here would get you foo₀ from the top scope
0

, .

, , :

function square(x) { return x*x; }

var square = function(x) { return x*x; }

square , "" :

function foo() {
    console.log(square(12));  // Valid, no prob the function is defined "later"
    function square(x) { return x*x; }
}

, , , , , .

, ( ).

What to do in the nested parts is not defined instead, and different implementations (for example, Firefox and Chrome) are not consistent. Obviously, nonsense is, for example, placing two definitions for the same function in two branches of an operator if- else(remember that name binding must occur immediately before the operators in the area begin execution).

Just don't do it.

-1
source

Source: https://habr.com/ru/post/1690252/


All Articles