Day 19 - Execution Context

JavaScript 在运作时会建立执行环境,分为 Global Execution Context(全域) 和 Function Execution Context(函式)两种。
而在执行环境建立的时候又分两个阶段,分别是 Creation Phase 和 Execution Phase,在 Creation Phase 时会建立 this 以及变数和函式的记忆体位置。
例如:
在 function 被执行前会先到 creation phase ,程序码正式被运行後,才会到 execution phase 这个阶段,并遵循 callstack 原则一行一行执行。

  • Global Execution Context
  • Function Execution Context

Hoisting

Hoisting 发生在 Creation phase
在执行程序码之前(creation phase)电脑的记忆体只会分配给 function declaration variable 和 var,并不会分配给 let,const 和 function expression。

例如:

会 hoist 的情况

  • var
console.log(x); // undefined
var x = 10;
console.log(x); // 10

在程序码被执行之前, JavaScript 会先找到 var ,再找到 x 这个变数,并放到记忆体里面,但 assignment 这件事情先不管,所以当第 1 行 console.log(x) 时会看到 undefined,因为电脑已经知道 x 是个变数,但里面还没被做 assignment
接着执行第 2 行时,就做 assignment,把 10 放进 x 里面,第 3 行 console.log(x) 就会看到 10 这个数字

  • function declaration
sayHi();
function sayHi(){
  console.log("Hi");
}
// Hi

在程序码被执行之前, JavaScript 会先找到 sayHi 这个 function 并丢到记忆体里面,当第 1 行被执行时,电脑会知道 sayHi 这个 function 里面的东西,所以会出现 Hi 的结果

不会 hoist 的情况

  • lexical declaration(let & const)
console.log(x);
let x = 10;
// Uncaught ReferenceError: Cannot access 'x' before initialization
  • arrow function expression
sayHi();
const sayHi = ()=>{
  console.log("Hi");
}
// Uncaught ReferenceError:Cannot access 'sayHi' before initialization 

Scope(作用域)

  • Global Scope
    不管是 var,let 还是 const 只要放在最外层,都含有 global scope
let myName = "Helen";
function sayHi(){
  console.log("sayHi: " + myName);
  function sayHi2(){
    console.log("sayHi2: " + myName);
  }
  sayHi2(); // sayHi2: Helen
}
sayHi(); // sayHi: Helen

myName 是全域变数,在任何地方都是有意义的,所以无论在哪里都可以找到 myName

  • function Scope
    无论是 var,let or const,他们如果在 function 中被宣告,就只能在 function 中被使用,离开了 function 就没有意义了
function sayHi(){
  let myName = "Helen";
  console.log(myName);
}
sayHi(); // Helen
console.log(myName); // Uncaught ReferenceError: myName is not defined 
  • Block Scope
    let & const 只在回圈和条件式中有意义
if(true){
  let x = 10;
  console.log(x); // 10
}
console.log(x); // Uncaught ReferenceError: x is not defined 

var 没有 block scope,因此使用 var 会有很多问题

if(true){
  var x = 10;
  console.log(x); // 10
}
console.log(x); // 10

Closure and Scope Chaining

在 Creation phase 会发生的事情

let myName = "Helen";
function sayHi(){
  let myName = "Mary";
  console.log("sayHi: " + myName); 
  sayHi2();
}
function sayHi2(){
    console.log("sayHi2: " + myName); 
  }
sayHi();
// sayHi: Mary
// sayHi2: Helen

如果在 function 中的变数并没有在 function 中被定义,则会跑去 function 被定义的地方找,function sayHi2 里的 myName 并没有在此 function 中被定义,所以会跑到 sayHi2 被定义的地方找(window),找到 myName 是 Helen

let myName = "Helen";
function sayHi(){
  let myName = "Mary";
  console.log(myName); // Mary
  
  function sayHi2(){
    console.log(myName); // Mary
  }
  
  function sayHi3(){
    let myname = "Lisa";
    sayHi2();
  }
  sayHi3()
}

sayHi();

sayHi3() 里执行 sayHi2() 时,因为 sayHi2() 并没有定义 myName,所以会跑到 sayHi2() 被定义的地方(sayHi()里)找,最终找到 myName 是 Mary

Call Stack

Call Stack工具
在执行 calling function 时会产生 stack
stack 是一种资料结构,可以想像成容器的概念,後面进去的要先出来

function fn1(){
  console.log("This is fn1");
  
  fn2();
  function fn2(){
    console.log("This is fn2")
    
    fn3();
    function fn3(){
      console.log("This is fn3")
    }
    console.log("Running")
  }
  console.log("Done")
}
fn1();
// This is fn1
// This is fn2
// This is fn3
// Runnung
// Done

<<:  [ Day 5 ] - 物件

>>:  接API

使用 Template Message 替 Line Bot 加上同意条款的功能(2)

昨天我们完成了 user sheet 的 query & upsert 功能,今天就要正式将...

Vue.js指令(v-model)绑定(DAY27)

现今常常会在购物网站中看到顾客点选产品时,网页会依据顾客的操作自动列出清单,或是看到一些使用者在输入...

Day28 vue.js搜寻栏 分页(pagination)功能

延续昨日 今天我们且战且走 首先先把最简单的排序专案方法搞定 先创一个sortby function...

温馨鬼故事 - 网购我的爱,我的个资跟着订单出去了

温馨鬼故事 - 网购我的爱,我的个资跟着订单出去了 Credit: Drake 故事开始 以下故事纯...

【领域展开 20 式】 Menu 修炼失败纪录手册

更动 Menu 大作战 暨【领域展开 13 式】 有了骨头与皮肤,再搞清楚主要肌群 Menu 层级与...