湯姆大叔的深入理解JavaScript讀後感二(17——24節)

今天要分享的內容是tom大叔的JavaScript系列的讀書觀後感2

border="0" width="330" height="86" src="//music.163.com/outchain/player?type=2&id=527602&auto=1&height=66">

第十七部分,面向對象編程之概論

我們有必要掌握一些OOP基本的特徵,並澄清概論中的主要概念。主要討論封裝,繼承,多態,接口,那些傳統的面向對象概念,可以忽略不看,不影響

第十八部分,面向對象編程之ECMAScript實現(推薦)

總結如下:

1. 原始值類型
   回頭來看6中用於ECMAScript程序的數據類型,前5種是原始值類型,包括Undefined、Null、Boolean、String、Number、Object。
2. 有必要需要注意的是規範還區分了這內置對象、元素對象和宿主對象。
所有ECMAScript實現的對象都是原生對象(其中一些是內置對象、一些在程序執行的時候創建,例如用戶自定義對象)。內置對象是原生對象的一個子集、是在程序開始之前內置到ECMAScript裏的(例如,parseInt, Match等)。所有的宿主對象是由宿主環境提供的,通常是瀏覽器,並可能包括如window、alert等。
也有對象是由特殊的內置構造函數創建: Function(函數對象構造器)、Array(數組構造器) RegExp(正則表達式構造器)、Math(數學模塊)、 Date(日期的構造器)等等,這些對象也是Object對象類型的值
3. 字面量Literal

   對於三個對象的值:對象(object),數組(array)和正則表達式(regular expression)
4. 然而,如果我們徹底改變函數的prototype屬性(通過分配一個新的對象),那原始構造函數的引用就是丟失,這是因爲我們創建的對象不包括constructor屬性:
function A() {}
A.prototype = {
  x: 10
};

var a = new A();
alert(a.x); // 10
alert(a.constructor === A); // false!
因此,對函數的原型引用需要手工恢復:

function A() {}
A.prototype = {
  constructor: A,
  x: 10
};

var a = new A();
alert(a.x); // 10
alert(a.constructor === A); // true
5. a.[[Prototype]] ----> Prototype <---- A.prototype

   此外, 實例的[[Prototype]]值確實是在構造函數的prototype屬性上獲取的。

   然而,提交prototype屬性不會影響已經創建對象的原型(只有在構造函數的prototype屬性改變的時候纔會影響到),就是說新創建的對象纔有有新的原型,而已創建對象還是引用到原來的舊原型(這個原型已經不能被再被修改了)。
  對象的原型是對象的創建的時候創建的,並且在此之後不能修改爲新的對象,如果依然引用到同一個對象,可以通過構造函數的顯式prototype引用,對象創建以後,只能對原型的屬性進行添加或修改。

  這個地方,原型鏈,特別難理解,詳細的看第一篇,觀後感的,原型鏈的,鏈接,那個是非常詳細的說明 
6. 有誤解:

   if (foo instanceof Foo) {
     ...
   }
   這不是用來檢測對象foo是否是用Foo構造函數創建的,
所有instanceof運算符只需要一個對象屬性——foo.[[Prototype]],在原型鏈中從Foo.prototype開始檢查其是否存在。

7. alert(1..toString()); // "1",不是語法錯誤
   大部分程序裏使用原型是用來存儲對象的方法、默認狀態和共享對象的屬性。

第十九部分,求值策略(Evaluation strategy)

很多程序員都確信在JavaScript中(甚至其它一些語言),對象是按引用傳參,而原始值類型按值傳參

1. 按值傳遞
   按值傳遞,很多開發人員都很瞭解了,參數的值是調用者傳遞的對象值的拷貝(copy of value),函數內部改變參數的值不會影響到外面的對象(該參數在外面的值),一般來說,是重新分配了新內存(我們不關注分配內存是怎麼實現的——也是是棧也許是動態內存分配),該新內存塊的值是外部對象的拷貝,並且它的值是用到函數內部的。
2. 按引用傳遞
   另外一個衆所周知的按引用傳遞接收的不是值拷貝,而是對象的隱式引用,如該對象在外部的直接引用地址。函數內部對參數的任何改變都是影響該對象在函數外部的值,因爲兩者引用的是同一個對象,也就是說:這時候參數就相當於外部對象的一個別名。
3. 按共享傳遞(Call by sharing)
最重要的區別就是:函數內部給參數重新賦新值不會影響到外部的對象(和上例按引用傳遞的case),但是因爲該參數是一個地址拷貝,所以在外面訪問和裏面訪問的都是同一個對象(例如外部的該對象不是想按值傳遞一樣完全的拷貝),改變該參數對象的屬性值將會影響到外部的對象。
4. 現在我們知道了ECMAScript中將對象作爲參數傳遞的策略了——按共享傳遞:修改參數的屬性將會影響到外部,而重新賦值將不會影響到外部對象
傳遞的是引用的拷貝(地址副本)

再強調一下,這裏所說對象的值是地址(address),而不是對象結構本身,將變量賦值給另外一個變量——是賦值值的引用。因此兩個變量引用的是同一個內存地址。下一個賦值卻是新地址,是解析與舊對象的地址綁定,然後綁定到新對象的地址上,這就是和按引用傳遞的最重要區別。

第二十部分,《你真懂JavaScript嗎?》答案詳解

總結如下:

1.  題目1

    if (!("a" in window)) {
        var a = 1;
    }
    alert(a);
   答案是undefined
2. var a = 1,
       b = function a(x) {
           x && a(--x);
       };
   alert(a);
   答案1
3. function a(x) {
       return x * 2;
   }
   var a;
   alert(a);
   答案 a函數
4. function b(x, y, a) {
       arguments[2] = 10;
       alert(a);
   }
   b(1, 2, 3);
   答案是10
5. function a() {
       alert(this);
   }
   a.call(null);
    答案是window

第二十一部分,S.O.L.I.D五大原則之接口隔離原則ISP

沒看懂,基本不用看

第二十二部分,S.O.L.I.D五大原則之依賴倒置原則DIP]

稍微看懂了,估計是因爲java看多了,ioc,基本不用看

第二十三部分,JavaScript與DOM(上)——也適用於新手

最重要的是Element, Text, Document。

 Element節點在頁面裏展示的是一個元素,所以如果你有段落元素(<p>),你可以通過這個DOM節點來訪問。
 Text節點在頁面裏展示的所有文本相關的元素,所以如果你的段落有文本在裏面的話,你可以直接通過DOM的Text節點來訪問這個文本
 Document節點代表是整個文檔,它是DOM的根節點。

nodeType類型,1是元素,2是屬性,3是text節點,詳細的type類型可以通過此地址:

    Node.ELEMENT_NODE == 1
    Node.ATTRIBUTE_NODE == 2
    Node.TEXT_NODE == 3
    Node.CDATA_SECTION_NODE == 4
    Node.ENTITY_REFERENCE_NODE == 5
    Node.ENTITY_NODE == 6
    Node.PROCESSING_INSTRUCTION_NODE == 7
    Node.COMMENT_NODE == 8
    Node.DOCUMENT_NODE == 9
    Node.DOCUMENT_TYPE_NODE == 10
    Node.DOCUMENT_FRAGMENT_NODE == 11
    Node.NOTATION_NODE == 12

第二十四部分,JavaScript與DOM(下)

node節點的2種類型,一種是元素節點,一種是text節點,上一章節已經列出了所有的節點類型,這兩種需要我們現在特別注意。創建元素可以通過createElement方法,而創建text節點可以使用createTextNode,相應代碼如下:
正如我們上章所說的,DOM和JavaScript語言是2個單獨的東西,瀏覽器事件是DOM API的一部分,而不是JavaScript的一部分。

‘mouseover’ – 鼠標移動到某元素上的時候觸發mouseover事件。
 ‘mouseout’ – 鼠標從某元素離開的時候觸發mouseout事件。
 ‘mousemove’ – 鼠標在某元素上移動但未離開的時候觸發mousemove事件。
 ‘change’ – 控件失去input焦點的時候觸發該事件(或者值被改變的時候)。

 ‘load’ – 頁面加載完畢(包括內容、圖片、frame、object)的時候觸發該事件。
 ‘resize’ – 頁面大小改變的時候觸發該事件(例如瀏覽器縮放)。
 ‘scroll’ – 頁面滾動的時候觸發該事件。
 ‘unload’ – 從頁面或frame刪除所有內容的時候觸發該事件(例如離開一個頁面)。

 嚴格來說,有2中不同的模型:W3C模型和微軟模型,除IE之外W3C模型支持所有的現代瀏覽器,而微軟模型只支持IE

 使用W3C模型的代碼如下:

 // 格式:target.addEventListener( type, function, useCapture );  
 // 例子:  
 var myIntro = document.getElementById('intro');
 myIntro.addEventListener('click', introClick, false);
 使用IE模型的代碼如下:

 // 格式: target.attachEvent ( 'on' + type, function );  
 // 例子:  
 var myIntro = document.getElementById('intro');
 myIntro.attachEvent('onclick', introClick);

 一個非常重要的內容是Event對象,當事件發生的時候出發某個函數,該Event對象將自動在函數內可用,該對象包含了很多事件觸發時候的信息,但IE卻沒有這麼實現,而是自己實現的,IE瀏覽器是通過全局對象window下的event屬性來包含這些信息

 例如當你想取消默認的行爲的時候你可以使用Event對象裏的preventDefault()方法,但IE裏不得不使用對象的returnValue屬性值來控制


 事件冒泡,就是事件觸發的時候通過DOM向上冒泡,首先要知道不是所有的事件都有冒泡。事件在一個目標元素上觸發的時候,該事件將觸發一一觸發祖先節點元素,直到最頂層的元素:
 如圖所示,如果a連接被點擊,觸發觸發連接的click事件,然後觸發p的click事件,以此再觸發div和body的click事件。順序不變,而且不一定是在同時觸發的。
 舉例來說,如果你有一個很多行的大表格,在每個<tr>上綁定點擊事件是個非常危險的想法,因爲性能是個大問題。流行的做法是使用事件委託。事件委託描述的是將事件綁定在容器元素上,然後通過判斷點擊的target子元素的類型來觸發相應的事件。
 事件委託依賴於事件冒泡,如果事件冒泡到table之前被禁用的話,那上面的代碼就無法工作了。

 經典的事件處理模型,微軟的冒泡,以及網景的捕獲模型,w3c的兩者兼容,網上例子很多,去看解釋
發佈了107 篇原創文章 · 獲贊 8 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章