JS-Javascript實現

一個完整的JavaScript的實現由三個部分組成:

  • 核心:ECMAScript
  • 文檔對象模型:DOM
  • 瀏覽器對象模型:BOM

ECMAScript

什麼是 ES
ECMAScript(簡稱ES)是由ECMA-262定義的。

ES 與 JS
ES可以理解爲是JavaScript的一個標準。實際上,JavaScript是ECMA-262標準的實現和擴展。

ES與Web瀏覽器
ES與瀏覽器沒有依賴關係。 Web瀏覽器只是ES實現可能的宿主環境之一,其他宿主環境包括node和Adobe flash。

ES6新增功能

ES6即ECMAScript的第6版。

let

let的特性 let-Javascript MDN

  1. let和const不會在全局聲明時創建window對象的屬性;而位於函數或代碼頂部的var聲明會給全局對象新增屬性
var x = 'global'
let y = 'global'
console.log(this.x) // "global"
console.log(this.y) // undefined
  1. let聲明的變量、語句或者表達式的作用域限制在塊級作用域中;var聲明的變量只能是全局或者整個函數塊的
var a = 1
var b = 2

if (a === 1) {
  var a = 11 // the scope is global
  let b = 22 // the scope is inside the if-block

  console.log(a) // 11
  console.log(b) // 22
}

console.log(a) // 11
console.log(b) // 2
  1. 初始化:let在編譯時才初始化
  2. 可以用來模仿私有成員,在處理構造函數時,通過let聲明而不是閉包來創建一個或多個私有成員
var Thing
{
  let privateScope = new WeakMap()
  let counter = 0
  Thing = function () {
    this.someProperty = 'foo'
    privateScope.set(this, {
      hidden: ++counter,
    })
  }
  Thing.prototype.showPublic = function () {
    return this.someProperty
  }
  Thing.prototype.showPrivate = function () {
    return privateScope.get(this).hidden
  }
}

console.log(typeof privateScope) // "undefined"
var thing = new Thing()
console.log(thing) // Thing {someProperty: "foo"}
thing.showPublic() // "foo"
thing.showPrivate() // 1
  1. 在同一個函數或塊作用域中重複聲明同一個變量會引起SyntaxError
// 在 switch 語句中只有一個塊
let x = 1
switch (x) {
  case 0:
    let foo
    break
  case 1:
    let foo // SyntaxError for redeclaration.
    break
}
// 解決方法:一個嵌套在 case 子句中的塊會創建一個新的塊作用域的詞法環境
let x = 1
switch (x) {
  case 0: {
    let foo
    break
  }
  case 1: {
    let foo
    break
  }
}
  1. 暫存死區與變量提升:let和const不存在變量提升,直到它們的定義被執行時才初始化;在變量初始化前訪問該變量會導致ReferenceError,該變量處在一個自塊頂部到初始化處理的“暫存死區”中
function do_something() {
  console.log(bar) // undefined
  console.log(foo) // ReferenceError
  var bar = 1
  let foo = 2
}
// 在同一行,這個if塊中的foo已經在詞法環境中被創建了,但是還沒有到達(或者終止)它的初始化(這是語句本身的一部分)
// 這個if塊裏的foo還依舊在暫存死區裏
function test() {
  var foo = 33
  {
    let foo = foo + 55 // ReferenceError
  }
}
test()
  1. 暫存死區與typeof:通過var聲明的變量有初始化值undefined,和未聲明變量的typeof都爲undefined;而let,使用typeof檢測在暫存死區中的變量, 會拋出ReferenceError異常
console.log(typeof undeclaredVariable) //打印出 undefined
console.log(typeof undeclaredVariable) //打印出 undefined
var varVariable
console.log(typeof i) //引發異常 ReferenceError: Cannot access 'i' before initialization
let i = 10

const

const聲明一個只讀的常量。一旦聲明,變量指向的那個內存地址不得改動(不是變量值不能改變),且聲明時必須立即初始化,不能留到以後賦值。const的作用域與let命令相同:只在聲明所在的塊級作用域內有效。
對於簡單類型的數據(數值、字符串、布爾值),值就保存在變量指向的那個內存地址,因此等同於常量。
但對於複合類型的數據(主要是對象和數組),變量指向的內存地址,保存的只是一個指針,const只能保證這個指針是固定的,至於它指向的數據結構是不是可變的,就完全不能控制了。因此,將一個對象聲明爲常量必須非常小心。如果真的想將對象或對象屬性凍結,應該使用Object.freeze方法。

const foo = {}; // const foo = []同理,可以正常使用push等功能
foo.prop = 123; // 爲foo添加一個屬性,可以成功
console.log(foo.prop); //123
foo = {}; // 將foo指向另一個對象,就會報錯

Class

Class ES2015
類的數據類型就是函數,類本身就指向構造函數

import

解構賦值

ES6允許按照一定模式,從數組和對象中提取值,對變量進行賦值,這被稱爲解構(Destructuring)。本質上,這種寫法屬於“模式匹配”,只要等號兩邊的模式相同,左邊的變量就會被賦予對應的值。

let a = 1;
let b = 2;
let c = 3;
// 等價於
let [a, b, c] = [1, 2, 3];
 
let [ , third] = ["foo", "bar", "baz"];
third // "bar"
 
let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]
 
let [x, y, ...z] = ['a'];
x // "a"
y // 變量解構不成功,賦值爲undefined
z // 數組解構不成功,賦值爲[]

解構賦值允許指定默認值,只有當一個數組成員嚴格等於undefined,默認值纔會生效:

let [foo = true] = []; // foo = true
let [x, y = 'b'] = ['a']; // x='a', y='b'
let [q = 1, w = 'b'] = ['a', undefined]; // q='a', w='b'
let [e = 1] = [null]; // e = null
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章