zuppachu / Joanne-s-Learning-Blog

程式導師實驗計畫第二期 之 Coding 學習紀錄。
2 stars 0 forks source link

[ JS201 ] - 課堂筆記 #17

Open zuppachu opened 5 years ago

zuppachu commented 5 years ago

七種資料型態

primitive types 原始型態 (immuable 不能改變)

  1. null
  2. undefined
  3. string
  4. number
  5. boolean
  6. symbol(ES6)

其他的都是屬於

  1. object 物件,如:arry、function、date...

用來測驗為哪種屬性,可用 ?

zuppachu commented 5 years ago

從 Hoisting 理解底層運作機制

什麼是 Hoisting ?

例一:

console.log(b)
var b = 10

可以「想像」成這樣的跑法,但不是真的:

var b 
console.log(b)
b = 10 // 賦值不會提升,但是宣告會。

兩個得到結果一樣 - undefined


例二:

test()

function test() {
  console.log(123)
}

想像跑法如下,函式整個提昇~

funciton test() {
   console.log(123)
}

test()

兩個得到結果一樣 - 123


例三:

var test = function(){
  console.log(123)
}

test()

你以為會跑成這樣

test()

var test = function(){
  console.log(123)
}
// 得 test is not a function

但其實是如下跑法,可將其分為兩步驟: 一個是賦值,一個是宣告。

var test 
test()
test = function() {
  console.log(123)
}
// test 是 undefined。賦值不會提升,宣告會提升。

上述的表現即是「提升」~


一個一個來:hoisting 的順序

function test(a) {
    console.log(a)
}
test(123)
// 得 123
function test(a) {
    console.log(a)
    var a = 456
}
test(123)
// 得 123。值不會被改變,因為 a 本來就有值了
function test(a) {
    console.log(a)
    function a() {
    }    
}
test(123)
// 得 function a
function test() {
    var a 
    console.log(a)
}

test()

// 得 undefined,因為預設的值就是 undefined。
function test() {
    var a = 'test'
    var a    //這邊會被忽略,因為他只代表我要宣告一個變數 a
    var a
    console.log(a)
}

test()

// 得 test

小結,提升的順序?

  1. function
  2. arguments 參數
  3. var

那hosting 跑程式碼的順序?

function test(a) {
    console.log(a)
    var a = 456
    console.log(a)
}
test(123)

// 得 123 , 得 456

hoisting 的原理為何? 從 ECMAScript 下手

先解題~題目如下: 2019-01-03 16 24 08 [圖片出自鋰學院 - JS201]

var a = 1;
function test(){
  console.log('1.', a);
  var a = 7;
  console.log('2.', a);
  a++;
  var a; //有跟沒有是一樣的,並不會變成 undefiend
  inner();
  console.log('4.', a);
  function inner(){
    console.log('3.', a);
    a = 30;
    b = 200;
  }
}
test();
console.log('5.', a);
a = 70;
console.log('6.', a);
console.log('7.', b);

解題:

  1. undefined => 因為 hoisting
  2. 7
  3. 8 => 因為 inner() 裡面沒有 a,只有被賦值 30,所以必須往上找 test() 裡面最後一個 a = 8 (a++)
  4. 30 => 因為 inner() 裡面的 a 最後被賦值 30
  5. 1
  6. 70
  7. 200 => b = 200 會被渲成全域變數

原理:

VO: {
    a: 123,
    b: function,
    c: undefined
}

function test(a,b) {
       function b() {}
       var c = 30
}

test(123)

體驗 JS 引擎的一天,理解 Execution Context 與 Variable Object

var a = 1;
function test(){
  console.log('1.', a);
  var a = 7;
  console.log('2.', a);
  a++;
  var a; //有跟沒有是一樣的,並不會變成 undefiend
  inner();
  console.log('4.', a);
  function inner(){
    console.log('3.', a);
    a = 30;
    b = 200;
  }
}
test();
console.log('5.', a);
a = 70;
console.log('6.', a);
console.log('7.', b);

執行真正原理如下!


--- step 3 ---
test EC
test VO {

}

---- step 1 進去 EC 的時候,step 2 之後進行程式碼 ---
global EC
global VO {
    test: func,
    a: undefined => 變成 1 
    // 1. 找參數 2. 找 func 的宣告 3. 變數的宣告
}

let 與 const 的詭異行為 + TDZ:Temporal Dead Zone (暫時性死區)

補充文章:我知道你懂 hoisting,可是你了解到多深?

zuppachu commented 5 years ago

從 Closure 更進一步理解 JS 運作

Closure 是什麼?

沒看很懂 QQ

從 ECMAScript 看作用域

閉包 跟 scope chain 有深深關係~

zuppachu commented 5 years ago

物件導向基礎與 prototype

ES5 的 Class vs ES6 的 Class

// ES5
function Dog(name) {
  this.name = name
}

Dog.prototype.getName = function() {
   return this.name
}

Dog.prototype.sayHello = function() {
    console.log(this.name)
}

var d = new Dog('abc')
d.sayHello()

var b = new Dog('123')
b.sayHello()
//ES6
Class Dog {
    constructor(name) {
             this.name = nam
}
getName() {
      return this.name
}
sayHello() {
      console.log(this.name)
  }
}

var d = new Dog('abc')
d.sayHello()

var b = new Dog('123')
b.sayHello()

為什麼要改變? 因為 ES5 的方法每次都要從新弄一個 function ,這樣太沒效率了。。

從 prototype 來看「原型鍊」

// ES5
function Dog(name) {
  this.name = name
}

Dog.prototype.getName = function() {
   return this.name
}

Dog.prototype.sayHello = function() {
    console.log(this.name)
}

var d = new Dog('abc')
console.log(d.__proto__ ===  Dog.prototype)
// true

尋找 d.sayHello() 會執行的方式:

(以下為原型鍊)

  1. d 身上有無 sayhello
  2. d.proto 有無 sayhello
  3. d.proto.__proto___ 有無 sayhello
  4. d.proto.proto.proto 有無 sayhello
  5. 找到 null

d.proto = Dog.prototype d.proto.proto = object.prototype Dog.prototype.proto = object.prototype

new 到底做了什麼事?

  1. 產生新的 object
  2. copy contructor 把新產生的 object 當成 this 丟進去 => 可以完成初始化的物件
  3. ???

繼承

class Dog {
   constructor(name) {
      this.name = name
   }
   sayHello() {
       console.log(this.name)
   }
}
class BlackDog extends Dog {   //extends 繼承
    constructor() {
      super() // = Dog.constructor
      this.sayHello()
    }
    test() {
     console.log('test', this.name)
    }
}

const d = new BlackDog('hello')

什麼時候使用? 共同的屬性時,例如:名字、種類... etc