DEV Community

MOYED
MOYED

Posted on

6. Function Scope, Block Scope and Lexical Scope

Articles


Functions

  • Functions are executed when they are called/invoked.
  • Functions always returns value. If value isn't given, it returns undefined.
  • Functions are objects. ### Defining functions #### Function Declaration
  • Named functions are declared.
  • Hoisted
add(1,2) // 3

function add(value1, value2) {
    console.log(value1 + value2);
    return 1;
  }
Enter fullscreen mode Exit fullscreen mode
  • Created in global scope #### Function Expression
  • Named or anonymous function are possible.
  • Not hoisted
addNumber(2,3); // "ReferenceError: Cannot access 'addNumber' before initialization

const addNumber = function (value1, value2) {
    console.log(value1 + value2);
    return 1;
  }
Enter fullscreen mode Exit fullscreen mode

Arrow function

  • Shorter syntax
  • Not create own this value
const addNumber = (value1, value2) => {
    console.log(this);
    return this;
  }

addNumber(2,3); // [object Window]
Enter fullscreen mode Exit fullscreen mode

IIFE(Immediately invoked function expressions)

((value1, value2) => {
    console.log(value1 + value2);
    return 1;
  })(2,3);
Enter fullscreen mode Exit fullscreen mode

Scope

Scope defines what variable we can access to.

Global scope

Variables declared outside function, block are all contained in global scope.

POLE; Principle of least exposure

We should minimize the exposure of variables registered in each scope. It means that we should try our best to avoid delcaring variables in global scope. Why?

  • Naming Collision

If we declare same name variable twice, it makes some problems. First, with var, the variable would shadow the previous value assigned. Second, with let and const , it would give error.

  • Unexpected behavior

Let' say that I declared data array in global scope. Then other developer can easily alter the value.

  • Unintended dependency

Let's say that I declared data array for specific function's argument. If other developer uses data array, unintended dependency has occured. If I plan to change this array into object, many parts using this array should be changed.

Local scope

Function scope

var is function scope. Precisely, Javascript had only function scope before ES6. It exists within the scope of function it's declared.

const password = "3";

function checkIf(input) {
  if(input == password) {
    console.log(true);
  }
  else {
    console.log(false);
  }
}
console.log(password); // 3
checkIf(3); // true
Enter fullscreen mode Exit fullscreen mode

Here, input parameter is declared in function checkIf scope. password variable is declared in global scope which is very vulnerable. So, How can we hide the password, still accessing to checkIf function?

function hidePassword() {
  const password = "3";

  return checkIf;
  function checkIf(input) {
    if(input == password) {
      console.log(true);
    }
    else {
      console.log(false);
    }
}
}

console.log(password); // ReferenceError: password is not defined
const testCase = hidePassword();
testCase(3); // true
Enter fullscreen mode Exit fullscreen mode

We hide the password in hidePassword function. As checkIf function is inside the hidePassword function and returned, we can access to this function.


const testCase =(()=>{
  const password = "3";
  return checkIf;
  function checkIf(input) {
    if(input == password) {
      console.log(true);
    }
    else {
      console.log(false);
    }
  }
})();

testCase(3); // true
Enter fullscreen mode Exit fullscreen mode

By using IIFE, we can write it more clearer, shorter.

Block scope

As let and const introduced in ES6, both keywords are block scope. {} becomes scope if it contains let or const.

function add(value1, value2) {
  {
    let value3 = 4;
  }
  console.log(value3);
}

add(1,2); // "ReferenceError: value3 is not defined"

Enter fullscreen mode Exit fullscreen mode

We have mentioned about POLE. So, it's best to put let or const declared variable in block scope as possible.


What is Lexical scope?

JS program processes in two phases; Compilation & Execution.
In compilation, JS Engine parses through the code and checks which variables corresponds to which scope. This means that scope of variables are determined before execution, which we call it lexical scope.
For example,

let a = "3";
console.log(a); // SyntaxError: Unexpected token '.'
let b = ."4";
Enter fullscreen mode Exit fullscreen mode

in this example, if there's no compilation phase, console.log(a) should work fine. However, as the error was found before execution phase, it return error.

Example

var name = 'zero';
function log() {
  console.log(name);
}

function wrapper() {
  var name = 'nero';
  log();
}
wrapper(); // zero
Enter fullscreen mode Exit fullscreen mode

function log scope was determined before execution. It is nested in global scope, not wrapper scope. So, as log is executed as wrapper is executed, first, engine looks at variable name in funciton log scope. As it is not declared in it, engine looks at outer scope, which is global scope. That's why it returns zero.

Top comments (0)