《JavaScript高級程序設計》讀書筆記-在讀

摘要

關於《JavaScript高級程序設計》中的事例代碼可在附件中查看。html

第二章 <script>元素

defer屬性

設置defer="defer",腳本會被延遲到整個頁面都解析完畢後在運行,多個延遲腳本並不必定會按照前後順序執行。前端

async屬性

設置async="async",異步加載腳本內容,可是多個異步腳本之間並不必定會按照前後順序執行。正則表達式

<noscript>元素

該元素能夠包含可以出如今<body>中的任何html元素(script除外),只有當瀏覽器不支持腳本或者支持腳本,可是腳本被禁用時,瀏覽器纔會顯示<noscript>中的內容。算法

第三章 基本概念

typeof操做符

typeof是一個操做符,可以返回該數據的數據類型。可是注意其中對於基本類型,除null(返回Object,null被認爲是一個空的對象引用)之外,都可以返回正確的結果;對於引用類型,除function(返回Function)之外,一概返回 object 類型。express

Boolean類型

使用Boolean()函數可以將任意類型的一個值轉換爲Boolean類型值。使用「!!data」可以達到一樣的效果,第一個邏輯非操做符是將值轉換爲布爾值而後取反,第二個邏輯非操做符再次取反獲取這個值真正的布爾值。數組

Number類型

JS中將最小值保存在Number.MIN_VALUE中,值爲5e-324;將最大值保存在Number.MAX_VALUE中,值爲1.7976931348623157e+308。若是某次計算的值超過這個範圍,這個值就會自動轉換爲特殊的Infinity值(Infinity爲正無窮,-Infinity爲負無窮),使用isFinite()能夠判斷一個值是否爲有窮。瀏覽器

NaN即非數值,涉及NaN的操做都會返回NaN而且NaN與任何值都不相等,包括NaN自己。isNaN()函數接受一個參數,可以判斷這個參數是否「不是數值」。NaN也適用於對象,首先調用對象的valueOf(),而後肯定返回值是否能夠轉換爲數值,若是不能,則基於這個返回值在調用toString(),在測試返回值。bash

Number()、parseInt()、parseFloat()三個函數可以將非數值轉換爲數值:app

  • Number():將任何數據類型轉換爲數值。null值轉換爲0;undefined轉換爲NaN;空字符串轉換爲0。
  • parseInt():將字符串轉換爲數值。空字符串轉換爲NaN。接受第二個參數設置轉換時的進制。
  • parseFloat():將字符串轉換爲數值,可以解析十進制。

String類型

將一個值轉換爲String有兩種方法。異步

  • 經過toString()方法:每一個值都存在toString()方法,返回相應值的字符串表現(null與undefined沒有這個方法)。在調用數值的toString()時,能夠傳遞一個參數,用來指定輸出數值的進制基數。
  • 使用轉型函數String(),若是值存在toString()方法,返回toString()相應的結果,而null與undefined返回「null」與「undefined」。

一元加操做符

一元加運算符除了用於基本的算術運算,對非數值應用一元加操做符時,可以像Number()轉型函數同樣對這個值執行轉換。

函數

因爲ECMAScript函數沒有簽名,其參數是由包含零或者多個值的數組來表示,而沒有函數簽名,真正的重載是不可能作到的。

第四章 變量、做用域和內存問題

變量值複製

  • 若是從一個變量向另外一個變量複製基本類型的值,會在變量對象上建立一個新值,而後將該值複製到爲新變量分配的位置上,兩個變量能夠參加任何操做而不會互相影響。
  • 當一個變量向另外一個變量複製引用類型的值時,由於變量中存儲的是對象的指針,因此會將指針值複製一份到新變量分配的空間中,所以複製結束後,兩個變量實際上將引用同一個對象,改變其中一個變量,會影響另外一個變量。

參數傳遞

把函數外部的值複製給函數內部的參數,就和把值從一個變量複製到另外一個變量同樣。基本類型值傳遞等同基本類型變量複製,引用類型值傳遞等同引用類型變量複製。

執行環境及做用域

每一個執行環境都有一個與之關聯的變量對象,其中定義了環境中的全部變量和函數。
當代碼在一個環境中執行的時候,會建立變量對象的一個做用域鏈。做用域鏈的用途是保證對執行環境有權訪問的全部變量和函數的有序訪問。做用域鏈的前端始終都是當前執行代碼所在環境的變量對象。
若是這個環境是函數,則將起活動對象做爲變量對象。活動對象最開始的時候只包含arguments對象。

變量聲明

使用var聲明的變量會自動被添加到最接近的環境中。若是初始化變量時沒有使用var聲明,該變量會自動添加到全局變量中。

垃圾回收

離開做用域的值將會被自動標記爲能夠回收,將在垃圾收集期間被刪除。
"標記清除"是目前主流的垃圾收集算法,給當前不使用的值加上標記而後回收其內存。
"引用計數"是跟蹤記錄全部值被引用的次數,可是目前已經不使用這種方式了,由於當存在循環引用的時候,「引用計數」算法就會致使問題。

第五章 引用類型

Object類型

建立Object實例的方式有兩種。一種是使用new操做符後面跟Object構造函數;另外一種是使用對象字面量表示法。在經過對象字面量定義對象的時候,實際上不會調用Object構造函數。

Array類型

建立數組的基本方式有兩種:

  • 第一種是使用Array構造函數,容許給構造函數傳遞參數,若是傳遞的數值就會按照該數值建立指定項數的數組,若是是其餘類型的參數,就會建立包含參數的數組;使用Array構造函數時能夠省略new操做符。
  • 第二種是使用數組字面量表示法,與對象同樣,在使用數組字面量表示法時,不會調用Array構造函數。

數組的length屬性不只僅只讀,經過設置這個屬性,能夠從數組的末尾移除項或向數組中添加新項。

數組的sort()排序方法,是先調用每個數組項的toString()方法,而後比較獲得的字符串,即便數組項是數值,也是比較的字符串;
sort()方法能夠接受一個比較函數做爲參數,比較函數設置有兩個參數,若是第一個參數應該位於第二個以前,則返回一個負數,以此類推。

Date類型

使用new操做符和Date構造函數可以建立一個基於當前日期和時間的日期對象。使用Date.parse()和Date.UTC()

  • Date.parse()接受一個表示日期的字符串參數,根據這個字符串返回相應日期的毫秒數。若是直接將表示日期的字符串傳遞給Date構造函數,後臺也會調用Date.parse()。
  • Date.UTC()接受的參數分別是年份、基於0的月份(一月是0)、月中的哪一天(1~31)、小時數(0~23)、分鐘、秒以及毫秒數,年和月爲必須的,其他默認爲最小值。將參數直接傳遞給Date構造函數,會基於本地時區建立時間。
// 兩者等同
var now = new Date("May 25, 2004");
var someDate = new Date(Date.parse("May 25, 2004"));

// GMT時間2000年1月1日0時
var gmtTime = new Date(Date.UTC(2000, 0));
// GMT時間2005年5月5日17時55分55秒 
var gmtTime2 = new Date(Date.UTC(2005, 4, 5, 17, 55, 55));

// 本地時間2000年1月1日0時
var localTime = new Date(2000, 0);
// 本地時間2005年5月5日17時55分55秒 
var localTime2 = new Date(2005, 4, 5, 17, 55, 55);
複製代碼

Date對toString()和toLocalString()進行了重寫,對於valueOf()返回的是日期毫秒錶示。

RegExp類型

正則表達式語法

var expression = / pattern/ flag
複製代碼

其中模式(pattern)部分能夠是任何簡單或複雜的正則表達式,每一個正則表達式均可以帶有一個或多個標誌(flag),正則表達式的匹配模式支持下列3個標誌:

  • g:表示全局(global)模式,即模式將被應用於全部字符串,而非在發現第一個匹配項時當即中止;
  • i:表示不區分大小寫(case-insensitive)式,即在肯定匹配項時忽略模式與字符串的大小寫;
  • m:表示多行(multiline)模式,即在到達一行文本末尾時還會繼續查找下一行中是否存在與模式匹配的項。

對於RegExp實例的exec(),若是沒有設置全局標誌(g),那麼在同一個字符串上屢次調用exec()將始終返回第一個匹配項的信息;若是設置了全局標誌(g),每次調用exec()會在字符串中繼續查找新匹配項。

Regexp的每一個實例都具備下列屬性,經過這些屬性能夠取得有關模式的各類信息。

  • global:布爾值,表示是否設置了g標誌。
  • ignorecase:布爾值,表示是否設置了i標誌。
  • lastindex:整數,表示開始搜索下一個匹配項的字符位置,從0算起.
  • multiline:布爾值,表示是否設置了m標誌。
  • source:正則表達式的字符串表示,按照字面量形式而非傳入構造函數中的字符串模式返回。

RegExp構造函數包含一些屬性,這些屬性適用於做用域中全部正則表達式。

  • input 最近一次要匹配的字符串
  • lastMatch 最近一次的匹配項
  • lastParen 最近一次匹配的捕獲項
  • leftContext input字符串中lastMatch以前的文本
  • multiline 布爾值,表示是否全部表達式都使用多行模式
  • rightContext input字符串中lastMatch以後的文本
var text = "this has been a short summer";
  var pattern = /(.)hort/g;
      
  /*
   * Note: Opera doesn't support input, lastMatch, lastParen, or multiline. * Internet Explorer doesn't support multiline.
   */        
  if (pattern.test(text)){
      alert(RegExp.input);               //this has been a short summer
      alert(RegExp.leftContext);         //this has been a            
      alert(RegExp.rightContext);        // summer
      alert(RegExp.lastMatch);           //short
      alert(RegExp.lastParen);           //s
      alert(RegExp.multiline);           //false
  }
複製代碼

Function類型

函數聲明與函數表達式的區別:解析器會率先讀取函數聲明,並使其在執行任何代碼以前可用;而函數表達式則必須等到解析器執行到它所在的代碼行纔會被解釋執行。

// 函數聲明
alert(sum(10,10));    //20 執行正常,在代碼執行以前,就將函數聲明添加到執行環境中了
function sum(num1, num2){
   return num1 + num2;
}  

// 函數表達式
alert(sum(10,10));    //causes an error 尚未執行到函數表達式,sum中尚未保存對函數的引用,程序報錯。
var sum = function(num1, num2){
   return num1 + num2;
}; 
複製代碼

因爲JS中的函數就是對象,所以函數也有屬性和方法,每一個函數都包含有兩個屬性,length和prototype。

  • length:length屬性表示函數但願接受的命名參數的個數。
  • prototype:對於引用類型來說,prototype保存他們全部實例方法的真正所在。換句話說,諸如toString()、valueOf()等方法實際上都保存在prototypr名下,只不過經過各自對象的實例訪問罷了。

每一個函數都包含有apply()和call(),這兩個方法的用途就是在特定的做用域中調用函數,實際上等於設置函數體內this對象的值。

  • apply()接受兩個參數,第一個參數是在其中運行函數的做用域,另外一個是參數數組,能夠是數組也能夠是arguments對象。
  • call()與apply的做用相同,只是接受參數的方式不同,第一個參數是在其中運行函數的做用域,而其他的參數必須一一傳遞給函數。
  • bind()會建立一個函數的實例,其中的this值會被綁定到傳給bind()函數的值
// apply() demo
function sum(num1, num2){
   return num1 + num2;
}
function callSum1(num1, num2){
   return sum.apply(this, arguments);
}
function callSum2(num1, num2){
   return sum.apply(this, [num1, num2]);
}
alert(callSum1(10,10));   //20
alert(callSum2(10,10));   //20

// call() demo
function sum(num1, num2){
   return num1 + num2;
}
function callSum(num1, num2){
   return sum.call(this, num1, num2);
}
alert(callSum(10,10));   //20

// bind() demo
window.color = "red";
var o = { color: "blue" };                    
function sayColor(){
   alert(this.color);
}
var objectSayColor = sayColor.bind(o);
objectSayColor();   //blue
複製代碼

apply()、call()、bind()這些方法的真正強大之處是可以擴充函數的做用域。

window.color = 'red';
var o = {color:'bluw'};

function sayColor() {
	alert(this.color);
}

sayColor();			// red

sayColor.call(this);	// red
sayColor.call(window);	// red
sayColor.call(o);		// blue
複製代碼

使用call()或者apple()、bind()來擴充做用域的最大好處就是對象不須要與方法有任何的耦合關係。 通常來講咱們須要將sayColor()函數放到對象o中,而後在經過o來調用它,而使用call()函數,咱們就不須要這麼作了,對象與方法沒有任何的耦合關係。

相關文章
相關標籤/搜索