【讀書筆記】JavaScript高階程式設計(第3版)(第5-7章)

weixin_33785972發表於2018-05-25

第5章 引用型別

5.1 Object型別

使用物件字面量定義函式時,最後一個屬性後面不要新增逗號。如

var person={
  name:"NIck",
  age:29
};

5.2 Array型別

Array.isArray(),確定某個值是否是陣列,通常用於條件語句。

toString()、valueOf()、toLocaleString(),返回由陣列中每個值的字串形式拼接而成的一個以逗號分隔的字串。

join(),接收分隔符引數,返回以這個分隔符分隔的陣列字串。不傳入值或傳入undefined,預設以逗號分隔。

棧方法,push()末端推入,pop()彈出末項,後進先出(LIFO)。

佇列方法,shift()移除第一項,push()末端推入,先進先出(FIFO)。

unshift()陣列前端新增任意項,pop()彈出末項,先進後出。

reverse(),反轉陣列項的順序。

sort(),按升序排列陣列項。需傳入比較函式sort(compare)。如

function compare(value1,value2){
  if(value1<value2){
  return -1;
  }else if(value1>value2){
  retrun 1;
  }else return 0;
}
var values=[0,1,5,10,15];
values.sort(compare);

concat(),基於當前陣列所有項建立新陣列。接收0或多個陣列作為引數。

slice(),基於當前陣列中一或多個項建立新陣列。接收1或2個引數,要返回的項的起始和結束位置。返回起始至結束位置之間的項但不包括結束位置的項。

splice(起始位置,刪除的項數,要插入的項),返回原陣列刪除項的陣列。可實現刪除Array.splice(0,1)、插入Array.splice(1,0,"red","blue")、替換Array.splice(1,1,"red","blue")操作。

indexOf()從前往後查詢,lastIndexOf()從後往前查詢,接收要查詢的項和表示查詢起點位置的索引。

every(),對陣列中每項執行給定函式,每一項返回true則返回true。

filter(),對陣列中每項執行給定函式,返回true項組成的陣列。

forEach(),對陣列中每項執行給定函式。

map(),對陣列中每項執行給定函式,返回撥用結果組成的陣列。

some(),對陣列中每項執行給定函式,如果有任一項返回true則返回true。

reduce()從前往後,reduceRight()從後往前,迭代陣列中所有項,返回最終值。

5.3 Date型別

Date()

Date.parse()

Date.UTC()

Date.now()

getTime()

setTime()

5.4 RegExp型別

var expression=/pattern/flags;正規表示式字面量。

元字元,([{^$|)?*+.]}在正規表示式中具有特殊用途,因此字串中出現時必須使用\轉義。

var expression=new RegExp("[bc]at","i");RegExp建構函式。

5.5 Function型別

函式有以下三種定義:
1、函式宣告function sum(num1,num2){//函式體}
2、函式表示式var sum=function(num1,num2){//函式體};
3、Function建構函式var sum=new Function("num1","num2","函式體");(不推薦)

解析器會率先讀取函式宣告,並使其在執行任何程式碼前可用;函式表示式必須等到解析器執行到它所在的程式碼才執行。

要訪問函式的指標而不是執行函式,必須去掉函式名後面的圓括號。

arguments主要用途數儲存函式引數,callee屬性是一個指標,指向擁有這個arguments物件的函式。函式中如要呼叫函式本身,可以使用arguments.callee()保證在更換函式名的情況下正常完成遞迴呼叫。

this引用的是函式據以執行的環境物件。

函式名僅僅是一個包含指標的變數而已。

caller屬性儲存著呼叫當前函式的函式引用,如果是在全域性作用域中呼叫當前函式,值為null。如function outer(){innder();}因為outer()呼叫了inner(),所有inner.caller指向outer(),返回outer()的原始碼。

出於安全性考慮,arguments.caller在嚴格模式下報錯,非嚴格模式下始終返回undefined。

函式的length屬性表示函式希望接收的命名引數的個數。

prototype儲存著引用型別所有例項方法。

apply()和call()在特定的作用域中呼叫函式。apply()接收this和引數陣列(可使用arguments)。call()接收this和逐個列出的引數陣列。它們能夠擴充函式作用域。

bind()建立函式一個函式例項,其this值會被繫結到傳給bind()函式的值。

5.6 基本包裝型別

三種基本包裝型別:Boolean、Number、String。基本型別值可以被當做物件來訪問。操作基本型別值的語句一旦執行完畢,就會立即銷燬新建立的包裝物件。

toFixed(),按照指定的小數位返回數值的字串表示。

toExponential(),返回以指數表示法表示的數值的字串形式。

toPrecision(),表示某個數值最適合的格式。

chartAt(),接收基於0的字元位置。返回給定位置的那個單字元字串。

chartCodeAt(),接收基於0的字元位置。返回給定位置的字元的字元編碼。

substr(),接收字串開始的位置和返回字串的個數。傳入負值時,第一個引數加上字串長度,第二個引數轉換為0。

substring(),接收字串開始的位置和字串最後一個字元後面的位置。傳入負值時,會把第二個引數轉換為0,將較小數作為開始位置,較大數作為結束位置。

trim(),建立一個字串副本,刪除前置及字尾的所有空格。

toLowerCase()、toLocaleLowerCase()、toUpperCase()、toLocaleUpperCase()字串大小寫轉換。

match(),接收一個引數,正規表示式或RegExp物件。返回陣列,陣列第一項是與整個模式匹配的字串,之後的每一項儲存著與正規表示式中的捕獲組匹配的字串。

search(),接收由字串或RegExp物件指定的一個正規表示式,返回字串中第一個匹配項的索引,沒有找到匹配項返回-1。

replace(),接收兩個引數,第一個引數是一個RegExp物件或字串,第二個引數是字串或者函式。如果第一個引數是字串,那麼只會替換第一個子字串;要替換所有字串,則必須提供正規表示式,且指定g標誌。返回替換後的字串。

split(),基於指定的分隔符將一個字串分割成多個子字串,並儲存為一個陣列。第二個引數指定陣列大小。

localeCompare(),比較兩個字串,返回負數(小於)、0(等於)、正數(大於)。

fromCharCode(),接收一或多個字元編碼,轉換成字串。

5.7 單體內建物件

encodeURI()、 encodeURIComponent()對URI進行編碼。前者用於整個URI,不會對本身屬於URI的字元進行編碼,如:/?#等。後者用於URI某一段,會對發現的任何非標準字元進行編碼。

decodeURI()、 decodeURIComponent()對以上方法編碼後的字元進行解碼。

eval(),接收要執行的javascript字串。eval()的任何變數或函式只在執行到該位置時建立。警惕使用eval()建立執行使用者輸入資料的程式碼。

Math.min()、Math.max(),確定一組數值中的最小最大值。

Math.floor(Math.random()*可能值的總數+第一個可能值),可以從某個範圍獲取某個值。

selectFrom(),接收兩個引數,應該返回的最小值和最大值。返回範圍內的某個值。

第6章 物件導向的程式設計

6.1 理解物件

ES中有兩種屬性:資料屬性、訪問器屬性。

資料屬性有4個描述其行為的特性:[[Configurable]]可配置,能否通過delete刪除屬性、重新定義屬性、修改為訪問器屬性,預設true;[[Enumerable]]可列舉,能否通過for-in迴圈返回屬性,預設true;[[Writable]]可寫,預設true;[[Value]]屬性值,預設undefined。

一旦把屬性定義為不可配置的,就不能再變回可配置的了。

Object.defineProperty()修改特性屬性,接收三個引數:屬性所在的物件、屬性的名字、描述符物件(可多個)。

在呼叫Object.defineProperty()時,如不指定,configurable、enumerable、writable特性預設值false。

Object.getOwnPropertyDescriptor()取得給定屬性的描述符,接收兩個引數:屬性所在的物件、要讀取其描述符的屬性。,預設true;[[Enumerable]]可列舉,能否通過for-in迴圈返回屬性,預設true;[[get]]讀取屬性時呼叫的函式,預設undefined;[[set]]寫入屬性時呼叫的函式,預設undefined。

屬性前加_,表示只能通過物件方法訪問。

只指定getter意味著屬性不能寫。

Object.defineProperties()通過描述符一次定義多個屬性。接收兩個物件引數:要新增和修改其屬性的物件、物件的屬性與第一個物件中要新增或修改的屬性一一對應。

Object.getOwnPropertyDescriptor()取得給定屬性的描述符,接收兩個引數:屬性所在的物件、要讀取其描述符的屬性名稱。

6.2 建立物件

工廠模式,用函式來封裝以特定介面建立物件的細節,如

function createPerson(name,age,job){
  var o=new Object();
  o.name=name;
  o.sayName=function(){
    alter(this.name);
  };
  return o;
}

建構函式模式,建立自定義建構函式,定義自定義物件型別的屬性和方法,建構函式應以大寫字母開頭,非建構函式應以小寫字母開頭。如

function Person(name,age,job){
  this.name=name;
  this.sayName=function(){
    alert(this.name);
  };
}

原型模式,prototype就是通過呼叫建構函式建立的物件例項的原型物件,可以讓所有物件例項共享它所包含的屬性和方法。如

function Person(){
}
Person.prototype.name="Nicholas";
Person.prototype.sayName=function(){
  alert(this.name);
};

更簡單的原型語法

function Person(){
}
Person.prototype={
  name:"Nicholas",
  sayName:function(){
    alert(this.name);
  }
};

預設情況下,所有原型物件都會自動獲得一個constructor(建構函式)屬性,這個屬性包含一個指向prototype屬性所在函式的指標。

isPrototypeOf(),如果[[prototype]]指向呼叫isPrototypeOf()方法的物件,那麼這個方法就返回true。

Object.getPrototypeOf()返回[[prototype]]的值。

每當程式碼讀取某個物件的某個屬性時,都會執行一次搜尋,目標是具有給定名字的屬性。搜尋首先從物件例項本身開始。如果在例項中找到了具有給定名字的屬性,則返回該屬性的值;如果沒有找到,則繼續搜尋指標指向的原型物件,在原型物件中查詢具有給定名字的屬性。如果在原型物件中找到了這個屬性,則返回該屬性的值。

不能通過物件例項重寫原型中的值,當為物件例項新增一個屬性時,這個屬性就會遮蔽原型物件中儲存的同名屬性。

delete操作符可以完全刪除例項屬性。

hasOwnProperty()方法可以檢測一個屬性是存在於例項中還是原型中,存在於物件例項中時返回true。

單獨使用in操作符會在通過物件能夠訪問給定屬性時返回true。

Object.keys()可以取得物件上所有可列舉的例項屬性,接收一個物件作為引數,返回一個包含所有可列舉屬性的字串陣列。

Object.getOwnPropertyNames()可以得到所有例項屬性。

Object.defineProperty()重設建構函式constructor屬性。

重寫原型物件切斷了現有原型與任何之前已經存在的物件例項之間的聯絡。

建立自定義型別最常見方式,是組合使用建構函式模式與原型模式。建構函式模式用於定義例項屬性,原型模式用於定義方法和共享的屬性。

動態原型模式,把所有資訊都封裝在建構函式中,通過檢查某個應該存在的方法是否有效,來決定是否需要初始化原型。

寄生建構函式模式,可以在特殊情況下用來為物件建立建構函式。基本思想是建立一個函式,作用僅為封裝建立物件的程式碼,然後再返回新建立的物件。建構函式在不返回值的情況下,預設返回新物件例項。返回的物件與建構函式或者與建構函式的原型屬性之間沒有關係。

穩妥建構函式模式,穩妥物件指的是沒有公共屬性,而且其方法也不引用this的物件,適合在安全環境(禁用this和new)和防止資料被其他應用程式改動時使用。

6.3繼承

原型鏈作為繼承的主要方法,是利用原型讓一個引用型別繼承另一個引用型別的屬性和方法。如SubType.prototype=new SuperType();

給原型新增方法的程式碼一定要放在替換原型的語句之後。通過原型鏈實現繼承時,不能使用物件字面量建立原型方法。

借用建構函式,解決原型中包含引用型別值所帶來的問題,通過在子型別建構函式的內部呼叫超型別建構函式。可以在子型別建構函式中向超型別建構函式傳遞引數。

組合繼承,將原型鏈和借用建構函式的技術組合到一起。使用原型鏈實現對原型屬性和方法的繼承,通過借用建構函式來實現對例項屬性的繼承。缺點是呼叫兩次超型別建構函式:一次在建立子型別原型的時候,一次在子型別建構函式內部。

原型式繼承,藉助原型可以基於已有的物件建立新物件,不必因此建立自定義型別。必須有一個物件可以作為另一個物件的基礎。

寄生式繼承,建立一個僅用於封裝繼承過程的函式,該函式在內部以某種方式來增強物件,最後再像真地是它做了所有工作一樣返回物件。

寄生組合式繼承,通過借用建構函式來繼承屬性,通過原型鏈的混成形式來繼承方法。本質上是使用寄生式繼承來繼承超型別的原型,再將結果指定給子型別的原型。

第7章 函式表示式

函式宣告提升,在執行程式碼前會先讀取函式宣告。

匿名函式的name屬性是空字串。把函式當成值來使用的情況下,都可以使用匿名函式。

函式表示式在使用前必須先賦值。

7.1 遞迴

遞迴函式,一個函式通過名字呼叫自身。呼叫自身時可以使用arguments.callee替代,嚴格模式下可以使用命名函式表示式來達成同樣效果。

7.2 閉包

閉包是指有權訪問另一個函式作用域中的變數的函式。建立閉包常見方式是在一個函式內部建立另一個函式。

將函式賦值給null可以解除匿名函式的使用。

作用域鏈的副作用,閉包只能取得包含函式中任何變數的最後一個值。可以通過建立另一個匿名函式強制讓閉包的行為符合預期。

匿名函式的執行環境具有全域性性,因此this物件通常指向window。把外部作用域中的this物件儲存在一個閉包能夠訪問的變數裡,就可以讓閉包訪問該物件。

如果閉包作用域鏈中儲存html元素,則該元素無法銷燬。閉包會引用包含函式的整個活動物件,需要將儲存著html的變數設定為null解除引用。

7.3 模仿塊級作用域

匿名函式可以模仿塊級作用域(私有作用域),讓變數只存在於塊級作用域內。如

(function(){
  //塊級作用域
})();

JavaScript將function關鍵字當作一個函式宣告的開始,函式宣告後面不能跟圓括號,而函式表示式後面可以跟圓括號,因此要將函式宣告轉換成函式表示式。

7.4 私有變數

任何在函式中定義的變數,都可以認為是私有變數。私有變數包括函式引數、區域性變數、函式內部定義的其他函式。

特權方法,如果在函式內部建立一個閉包,閉包通過自己的作用域也可以訪問這些變數。

利用私有和特權成員,可以隱藏那些不應該被直接修改的資料。

利用原型定義特權方法,訪問到的屬性是靜態的、由所有例項貢獻的。

模組模式,為單例建立私有變數和特權方法。單例指的是隻有一個例項的物件。如果必須建立一個物件並以某些資料對其進行初始化,同時還要公開一些能夠訪問這些私有資料的方法,就可以使用模組模式。

在返回物件前加入對其增強的程式碼,適用於單例必須是某種型別的例項,還必須新增某些屬性或方法的情況。

相關文章