今天要分享的內容是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的兩者兼容,網上例子很多,去看解釋