讀書筆記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以後的部分加以整理,貼到這裡。 感興趣可以檢視原文章。
#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
屬性代表陣列長度,此長度不包括index
和input
屬性。
如果不是全域性模式,每次呼叫
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