1. 程式人生 > >讀書筆記5:引用型別

讀書筆記5:引用型別

本章節內容多且碎,也都是非常基礎的內容,但同時因為其基礎,往往容易被忽略,所以本章整理會有較多的細節,內容比較繁瑣。 在這裡插入圖片描述

#1 類和物件

ECMAScript 中,引用型別是一種資料結構,用於將資料和功能組織在一起。

(1)類的概念

  • 類的實質是一種資料型別,類似於int、char等基本型別,不同的是它是一種複雜的資料型別。
  • 本質是型別,而不是資料,不存在於記憶體中,不能被直接操作,只有被例項化為物件時,才會變得可操作。

ECMAScript 從技術上講是一門面向物件的語言,但它不具備傳統的面嚮物件語言所支援的類和介面等基本結構。

(2)類和物件的關係

  • 物件是對客觀事物的抽象,類是對物件的抽象。
  • 物件是類的例項,類是物件的模板。

#2 Object型別

(1)建立方式

有兩種建立方式

  • 使用 new 操作符後跟 Object 建構函式
  • 使用字面量表示法。此方法定義物件,實際上不會呼叫Object建構函式(字面量形式的物件預設以Object為原型物件)

(2)訪問物件屬性方式

訪問一個 Object 型別值的屬性,有兩種方式: 第一種是,使用點表示法訪問物件屬性;第二種是,使用方括號表示法訪問物件屬性,屬性名需使用字串形式,支援變數,可以包含非字母、非數字

#3 Array型別

(1)建立方式

  • 使用Array建構函式。引數為非數字或多個數字時,傳遞的引數作為新陣列的元素;引數為單個數字
    時,表示新陣列的長度。
  • 使用陣列字面量表示法。同樣,也不會呼叫Array建構函式。

(2)訪問方式

訪問的方式非常簡單,就是使用方括號訪問相應索引的值;但當索引超過現有的項數,也不會報錯,陣列會自動新增為 undefined 值,此值實際上並不存在。

(3)陣列長度

  • 通過陣列的 length 屬性,讀取陣列的項數;
  • length 屬性也可設定陣列長度,從陣列的末尾移除項或者新增新項(新項值為 undefined);
  • 設定超過陣列長度的項的值,長度會因此改變,中間的空缺項會是 undefined

let arr = [1,2,3];
arr[8] = 9;
console.log(arr.
length); // 輸出10 console.log(arr[7]); //輸出 undefined

(4)檢測陣列

根據前面的內容,我們可能會使用 instanceof 操作符來檢測某個物件是不是陣列。當網頁中包含多個框架時,多個全域性環境下可能會存在多個 Array 建構函式,導致出現bug。所以 ES5 中新增 Array.isArray() 方法,適應性更強,推薦使用。

(5)轉換方法

  • toString()toLocaleString() 兩個方法,都可以返回陣列的字串表示,中間以逗號分隔。特別的是,toLocaleString() 處理日期物件、數字(超過4位)時,會有特定的格式,這跟地區和瀏覽器有關。(參考博文
  • valueOf() 方法返回陣列本身。
  • jion() 使用指定的分隔符構建字串。

(6)陣列方法

書中提及的陣列方法有多種型別,我將它們整理出來,利於記憶,形成一張表格如下 陣列方法總結

(7)ES5 到 ES8 陣列內容

前幾天在“前端早讀課”公眾號中瀏覽到這部分內容,介紹了從ES5到ES8的關於陣列的內容,其中著重介紹了一些方法。我將ES5以後的部分加以整理,貼到這裡。 感興趣可以檢視原文章ES6、ES7陣列內容

#4 Date型別

Date型別資料,使用自UTC時間1970年1月1日0時開始經過的毫秒數來儲存。

(1)日期解析

將字串或數字解析為 Date 型別資料,有兩個方法:

  • Date.parse() 接受常見的日期格式字串,但不支援中文;不同瀏覽器支援不同,所以儘量使用標準格式,如:2018/09/20。
  • Date.UTC() 依次接收年份、月份、日、時分秒毫秒引數。注意:月份取0-11,超過11會自動就算增加年份;日期天數是1-31;只能使用24小時時間格式。

(2)建構函式Date

不帶new操作符使用時,相當於一個函式,返回的是當前日期的字串;帶new操作符時,返回的是Date型別物件。

let time1 = Date("2018/09/20");
let time2 = new Date("2018/09/20");
console.log(typeof time1); // "string"
console.log(typeof time1); // "object"

給 Date 建構函式提供不同的引數,得到的結果會有差異

  • 不提供引數時,使用當前時間和日期建立 Date 物件;
  • 提供毫秒數時,使用從 GMT(格林威治平均時間)時間 1970年1月1日凌晨到期望日期和時間之間的毫秒來建立 Date 物件;
  • 提供日期格式字串,使用特定的表示期望日期和時間的字串來建立 Date 物件。該字串的格式應該與 Date 物件的 parse 方法相匹配;
  • 數字格式包含( year, month, day, hours, minutes, seconds, milliseconds ),使用年、月、日、小時、分、秒、毫秒的形式建立 Date 物件。格式與 Date 物件的 UTC 方法相匹配。

(3)繼承的方法

  • toLocaleString() 與瀏覽器設定的地區相適應的格式返回日期和時間,不同瀏覽器、不同時區格式不一樣;
  • toString() 返回帶有時區資訊的日期和時間;
  • valueOf() 返回日期的毫秒錶示。

(4)相關概念

  • 格林威治時間/世界時間,Greenwich Mean Time,是指格林威治所在地的標準時間;
  • UTC/協調世界時,Coordinated Universal Time,協調世界時是以原子時秒長為基礎,在時刻上儘量接近於世界時的一種時間計量系統;
  • PST/太平洋標準時間,Pacific Standard Time,加拿大及美國太平洋標準時間,美國西部城市通用的標準時間,以舊金山的時間為準;
  • 時間戳,Timestamp,指格林威治時間1970年01月01日00時00分00秒(北京時間1970年01月01日08時00分00秒)起至現在的總秒數。

#5 RegExp型別

(1)定義方法

定義 RegExp 型別值的方式有兩種,

  • 第一種,是正則表示式字面量,也是我們常用的方式;
  • 第二種,使用 RegExp 建構函式,接受兩個字串格式的引數,第一個引數是要匹配的字串模式;第二個引數是標誌字串,即g、i、m中的一個或多個。

(2)RegExp 例項方法

  • test() 檢測字串中的正則匹配,若匹配返回 true
  • exec() 最重要的正則方法,檢驗字串中的正則匹配,返回存放匹配結果的陣列(或null)。存放匹配結果的陣列中,第 0 個元素是與正則表示式相匹配的文字;第 1 個元素是與 RegExpObject 第 1 個子表示式相匹配的文字;第 2 個元素是與 RegExpObject 第 2 個子表示式相匹配的文字(以此類推);還有 index 屬性宣告的是匹配文字的第一個字元的位置;input 屬性則存放的是被檢索的字串;length 屬性代表陣列長度,此長度不包括 indexinput 屬性。

如果不是全域性模式,每次呼叫 exec() 返回的都是第一個匹配項; 如果是全域性模式,每次呼叫 exec() 返回字串中的下一個匹配項,直至搜尋到字串末尾為止。

(3)RegExp 建構函式屬性

  • input 最近一次要匹配的字串
  • lastMatch 最近一次的匹配項
  • lastParen 最近一次匹配的捕獲組
  • leftContext input 字串中 lastMatch 之前的文字
  • multiline 是否所有表示式都使用多行模式
  • rightContext input 字串中的 lastMatch 之後的文字
  • $1-9 儲存捕獲組,使用 exec()test() 方法時,會自動填充,可以直接讀取這些值

#6 Function型別

(1)定義方式及其區別

函式的定義方式有三種,他們的區別如下

  • 第一種,函式宣告,解析器會率先讀取函式宣告,在執行任何程式碼之前可用;
  • 第二種,函式表示式,必須執行到所在程式碼行,才會真正被解釋執行;
  • 第三種,Function建構函式,它接受任意數量的引數,最後一個引數是函式體;一般不建議使用這種方法,因為它需要二次解析,影響效能。

(2)函式內部屬性

  • arguments 存放實際傳入函式的引數,它的 callee 屬性指向擁有這個 arguments 物件的函式,實際使用中,可以降低程式碼耦合(比如使用遞迴時);
  • this 指的是函式執行的環境物件;
  • caller 儲存著呼叫當前函式的函式的引用,如果在全域性作用域中呼叫當前函式,它的值是null 。

(3)函式的屬性和方法

  • length 函式希望接收的命名引數的個數;
  • prototype 儲存函式所有例項方法的真正所在,原型相關,後續章節會專門提及;
  • apply() / call() 方法,最關鍵的作用是擴充函式的作用域;
  • bind() 方法,this 值會被繫結到傳給 bind() 函式的值;bind 方法建立的是例項,不是執行了該函式;可以通過 bind() 傳引數,也可以在使用新例項時傳引數。
function greetingTo(yourName) {
    return `Hello ${yourName}, I'm ${this.name}`;
};

let me = {name: 'Shawn'}, // me 物件中有一個 name 屬性
	you = 'Tom';
this.name = 'John'; // window 物件中也有一個 name 屬性

console.log(greetingTo(you)); // 結果: Hello Tom, I'm John
							  //沒有繫結的情況下,函式執行時 this 指向 window 物件(非嚴格環境)
							  
console.log(greetingTo.bind(this, you));  // 結果顯示的是一個函式表示式: f greetingTo(yourName) { ... }
										  // bind 方法建立的是例項,不是執行了該函式
										  
console.log(greetingTo.bind(this, you)()); // 結果:Hello Tom, I'm John
										   //  bind 方法繫結 this(即 window 物件) 且執行了該函式(後面的小括號)
										   //  bind 方法繫結同時將引數 you 傳遞給例項
										   
console.log(greetingTo.bind(me)(you)); // 結果:Hello Tom, I'm Shawn
									   //  bind 方法繫結 me ,例項中的 this 指向 me
									   //  例項執行的時候再將引數 you 傳遞給例項

console.log(greetingTo.bind(this, you)('Tony')); // 結果:Hello Tom, I'm John
									   			 //  bind 方法繫結同時將引數 you 傳遞給例項
									   			 //  例項執行的時候再傳遞的引數不生效

#7 基本包裝型別

使用 new 操作符呼叫基本型別的建構函式,建立基本包裝型別的例項,生成的是一個物件,擁有屬性;對基本包裝型別的例項呼叫 typrof 會返回 “object” 。

不建議顯式地建立基本包裝型別的物件。

基本包裝型別的物件,一般建議使用,正常使用基本型別值即可。我們需要理解的是他們支援的方法。三種類型的繼承方法及特殊方法,整理如下表: 基本包裝型別方法

補充 String 型別 slice()、substring()、substr()三種方法對於負數引數的處理區別: 在這裡插入圖片描述

#8 單體內建物件

在阮一峰《ECMAScript 6 入門》中提到,在ES5中,頂層物件的屬性與全域性變數是等價的,全域性作用域中宣告的所有變數和函式,都會成為 window 物件的屬性。 到 ES6 以後,let命令、const命令、class命令宣告的全域性變數,不屬於頂層物件的屬性。

頂層物件,在瀏覽器環境指的是window物件,在 Node 指的是global物件

以上,就是《Javascript高階程式設計》第五章的學習筆記。

Mark,這章書看的非常疲憊,內容實在太過碎,細讀真是一件傷腦筋的事情。。。 o(╥﹏╥)o