讀《學習JavaScript數據結構與演算法》- 第3章 數組,本節將為各位小伙伴分享數組的相關知識:概念、創建方式、常見方法以及ES6數組的新功能。 ...
定場詩
八月中秋白露,路上行人凄涼;
小橋流水桂花香,日夜千思萬想。
心中不得寧靜,清早覽罷文章,
十年寒苦在書房,方顯才高志廣。
前言
洛伊安妮·格羅納女士所著的《學習JavaScript數據結構與演算法》第三版於2019年的5月份再次刊印發行,新版內容契合當下,實為JavaScript開發人員的必備之佳作。有幸重讀此版,與諸君分享共勉。
內容提要
此章節為第2章-ECMAScript與TypeScript概述,主要介紹了JS和TS的相關概念,以及在JS新版本中的新特性:let、解構、箭頭函數等。
2.1 ECMAScript還是JavaScript
ECMA是一個將信息標準化的組織。ECMAScript是一個語言的標準,而JavaScript是該標準(最流行)的一個實現。
或恰如:ECMAScript是JS身份證上的名字(標準),JavaScript是常用的稱呼(常見、親切)。
JS的版本問題
版本 | 簡稱 | 發佈時間 | 備註 |
---|---|---|---|
ECMAScript5 | ES5 | 2009年12月 | |
ECMAScript2015 | ES6 | 2015年6月 | ECMAScript規範委員會決定每年更新標準一次,js的標準稱呼為:ECMAScript+年份 |
ECMAScript2016 | ES7 | 2016年6月 | ECMAScript第7個版本 |
ECMAScript2017 | ES8 | 2017年6月 | ECMAScript第8個版本 |
ES.NEXT | 泛指下一個版本的ECMAScript |
JS版本的相容性問題
一定要明白,即便ES2015到ES2017已經發佈,但不是所有的瀏覽器都支持新特性。
- 使用最新版的瀏覽器進行體驗
使用Babel.js對使用ECMAScript新語言特性的JavaScript代碼轉換成只使用廣泛支持的ES5特性的等價代碼
Babel.js是一個JavaScript的轉譯器,具體使用文檔:官網-傳送門 Babel.js中文網
2.2 ES6+的新功能
let和const定義變數
不存在變數提升
console.log(a) // ReferenceError: Cannot access 'a' before initialization let a = 10
不允許重覆聲明定義變數
let a = 10 let a = 20 // SyntaxError: Identifier 'a' has already been declared
變數作用域
塊狀作用域 {}
if (true) { const b = 10 } console.log(b) // ReferenceError: b is not defined
let和const到底選擇誰?
const與let的行為是一樣的,唯一的區別在於,使用const定義的變數是只讀的,也就是常量。
const保證的其實並不是變數的值不能改動,而是變數指向的記憶體地址所保存的數據不得改動。
擴展:基本類型值和引用類型值
每一個變數都指向了一個記憶體地址。
基本類型值
:指向了一個記憶體地址,變數的值就存儲在改記憶體內置中。
引用類型值
:指向了一個記憶體地址,該記憶體地址中存儲的是一個指針,一個指向實際數據的指針。
const保證的是這個指針是固定的,總是指向另一個固定地址;但實際上指針指向的數據結構是否可變,則不能控制。
模板字面量
模板字面量語法``提供了很大的幫助,支持JS書寫時換行,可定義多行字元串;使用${}插入變數的值。
let person = {
name: '王二狗',
age: 18
}
let str = `給你介紹個人:
這個人的名字是${person.name}
`
console.log(str)
箭頭函數
箭頭函數 () => {} 簡化了函數語法
let f = () => {
console.log('我是箭頭函數....')
}
f()
// 簡化return關鍵字
let sum = (a, b) => a+b
sum(1, 2)
函數參數預設值
支持定義函數參數的預設值
function sum (x = 1, y = 2, z = 3) {
return x + y + z
}
聲明展開與剩餘參數
展開運算符... 將對象或數組展開為一層,亦可當做剩餘參數
let p = {
name: '人',
age: 20,
sex: '男'
}
let wangErGou = {
...p,
name: '王二狗'
}
console.log(wangErGou)
// 剩餘參數
function sum (x, y, ...a) {
return x * y * a.length
}
sum(1, 2, 2, 'abc', true) // 6 等同於a是數組[2, 'abc', true]
解構
數組與對象解構
let [x, y] = [10, 20]
console.log(x, y) // 10, 20
let {age, name} = {
name: '李四',
age: 20
}
console.log(name, age) // 李四, 20
數組解構中許註意順序,對象解構中無需註意順序;解構中無對應的值,則改值為undefined
解構應用
- 交換變數值
let x = 10
let y = 20
[y, x] = [x, y]
- 屬性簡寫
let x = 10
let y = 10
let obj = {x, y} // 相當於 {x: x, y: y}
簡寫方法名
對象中的方法名可簡寫
let obj = {
name: '王二狗',
print () {
console.log(this.name)
}
}
使用類進行面向對象編程
定義
class Book {
constructor (title, author, isbn) {
this.title = title
this.author = author
this.isbn = isbn
}
printIsbn () {
console.log(this.isbn)
}
}
let book = new Book('郭德綱相聲選', '郭德綱', '00111011')
book.printIsbn()
繼承
class ITBook extends Book {
constructor (title, author, isbn, technology) {
// 代表調用父類構造函數
super(title, author, isbn)
this.technology = technology
}
printTechnology () {
console.log(this.technology)
}
}
let jsBook = new ITBook('JS數據結構與演算法', 'Groner', '123456789', 'JavaScript')
jsBook.printIsbn()
jsBook.printTechnology()
乘方運算符
let r = 2
let area = Math.PI * r ** 2
console.log(area)
模塊
- CommonJS規範是伺服器端模塊化開發規範,使用require方法載入;
- AMD(Asynchronous Module Definition) 非同步模塊定義,RequireJS是AMD最流行的實現,是瀏覽器端模塊化開發規範;
- CMD(Common Module Definition) 通用模塊定義,SeaJS是CMD的流行實現,是瀏覽器端模塊化開發規範
ES6模塊化開發
export 導出模塊;import 導入模塊
// moduleA.js
export const moduleA = 'moduleA'
// html中引入,註意type="module"
<script type="module">
import { moduleA } from './moduleA.js'
console.log(moduleA)
</script>
2.3 介紹TypeScript
TypeScript是一個開源的、漸進式包含類型的JavaScript超集,由微軟創建並維護。目的是讓開發者增強JavaScript的能力並使應用的規模擴展變得更容易。
TS在JavaScript中提供類型支持可以實現靜態檢查,從而更容易地重構代碼和尋找BUG。最後,TypeScript為被編譯為簡單的JavaScript代碼。
編寫時為.ts文件,使用TypeScript對其進行tsc編譯,最終為js文件
下載TypeScript
npm i -g typescript
創建.ts文件,寫入內容
// demo.ts
let a = '初始化為字元串內容'
a = 10
console.log(a)
編譯ts文件
tsc demo.ts
此處回生成demo.js文件,同時控制台報警告信息:error TS2322: Type '10' is not assignable to type 'string'. 說明TS對變數類型進行了校驗,但並未阻止編譯器生成最終的js代碼。
TS類型推斷
// 定義變數,並約束變數類型
let age: number = 20
let flag: Boolean = true
TS允許我們給變數設置一個類型,但是此種寫法太麻煩。TS提供了便捷的類型推斷機制,相當於在給變數賦初始值時就約束了變數的類型。
// 上面的代碼改造
let age = 20 // 數值類型
let flag = true // 布爾值類型
那麼,什麼時候需要給變數設置類型呢?聲明變數,但沒有設置其初始值的時候!
如果沒有給變數設置類型,那麼它的類型會被自動設置為any,意思為接受任何類型的值。
介面
在TS中,有兩種介面概念:
第一種:給變數設置類型,是對一個對象必須包含的屬性和方法的描述
interface Person {
age: number,
name: string
}
function printName (person: Person) {
console.log(person.name)
}
const john = {
name: 'john',
age: 21
}
const mary = {
name: 'mary',
age: 20,
phone: '123456'
}
printName(john)
printName(mary)
執行tsc編譯,木有任何問題。但是小伙伴可能會比較奇怪,對象mary中屬性多了個phone,但是並未影響代碼的執行。
鴨子類型概念:如果它看起來像鴨子,像鴨子一樣游泳,像鴨子一樣叫,那麼它一定是一隻鴨子!
變數mary的行為與Person介面定義的一樣,那麼它就是一個Person。
第二種:TS介面的概念和麵向對象編程相關
介面視為一份合約,在合約里可以定義這份合約的類或介面的行為
interface Comparable {
compareTo (b): number
}
class myObject implements Comparable {
age: number
compareTo(b): number {
if (this.age === b.age) {
return 0
}
return this.age > b.age ? 1 : -1
}
}
let obj = new MyObject()
obj.age = 10
let res = obj.compareTo(20)
console.log(res) // -1
Comparable介面告訴MyObject類,它需要實現一個叫做compareTo的方法,並且該方法接收一個參數。
泛型
對數據結構和演算法作用強大的TS特性是泛型這一概念
interface Comparable<T> {
compareTo (b: T): number
}
class MyObject implements Comparable<MyObject> {
age: number
compareTo(b: MyObject): number {
if (this.age === b.age) {
return 0
}
return this.age > b.age ? 1 : -1
}
}
let obj = new MyObject()
obj.age = 10
let obj2 = new MyObject()
obj2.age = 20
let res = obj.compareTo(obj2)
console.log(res) // -1
後記
以上就是胡哥今天給大家分享的內容,喜歡的小伙伴記得收藏
、轉發
、點擊右下角按鈕在看
,推薦給更多小伙伴呦,歡迎多多留言交流...
胡哥有話說,一個有技術,有情懷的胡哥!京東開放平臺首席前端攻城獅。與你一起聊聊大前端,分享前端系統架構,框架實現原理,最新最高效的技術實踐!
長按掃碼關註,更帥更漂亮呦!關註胡哥有話說公眾號,可與胡哥繼續深入交流呦!