![](http://static.javashuo.com/static/loading.gif)
一本很是值得推薦的書,看了前幾章以爲收穫還挺大的,因而整理成了筆記。本篇博客主要是一到三章的內容,也是書籍所分的第一部分,基礎知識,後續內容會盡快更新的。javascript
主要內容:動態類型語言、鴨子類型、this、call、apply、閉包、高階函數。java
第一章、面向對象的JavaScript
- 動態類型語言和鴨子類型
- 編程語言按照數據類型大致能夠分爲兩類,靜態類型語言和動態類型語言
- 靜態類型語言在編譯時就能發現類型不匹配的錯誤,規定了數據類型,編譯器還能夠對程序進行一些優化,提升程序執行的速度,缺點是會增長更多的代碼
- 動態類型語言的優勢是編寫的代碼數量更少,專一於邏輯表達,缺點是沒法保證變量的類型
- 鴨子類型:關注對象的類型,而不關注對象的自己
- 根據鴨子類型的思想,咱們沒必要藉助於超類,就能夠輕鬆的實如今動態類型語言中實現的一個原則:‘面向接口編程,而不是面向實現編程’
- 多態
- 含義:同一操做做用於不一樣的對象上面,能夠產生不一樣的結果
- 多態背後的思想是將‘作什麼’和‘說去作以及怎樣作’分離開來,也就是將不變的事物和可能改變的事物分離開來
- JavaScript對象的多態性是與生俱來的
- 面向對象設計的優勢是將行爲分佈在各個對象中,並讓這些獨享負責本身的行爲
- 封裝
- 封裝的目的是將信息隱藏
- 封裝數據只能模擬出public private兩種封裝性,函數建立做用域,let,經過symbol建立私有屬性
- 封裝的實現:封裝使得對象內部的變化對其餘對象而言是透明的,也就是不可見的,對象對本身的行爲負責。其餘對象或者用戶都不關心它的內部實現,使得對象之間的耦合變鬆散
- 封裝是靜態語言中一種重要的封裝方式,通常把對象真正類型隱藏在抽象類和接口以後,相比對象類型,客戶更關心對象的行爲,促使工廠方法模式,組合模式的產生,javaScript中沒有對抽象類和接口進行支持,沒有能力進行封裝。
- 原型模式和基於原型繼承的JavaScript對象系統
- 使用克隆的原型模式
- 克隆是建立對象的手段
- 原型編程範型的規則
- 全部數據都要是對象
- 要獲得一個對象不是經過實例化類,而是找到一個對象做爲原型克隆他
- 對象會記住它的原型
- 若是對象沒法響應某個請求,他會把這個請求委託給本身的原型
- JavaScript的原型繼承
- 全部數據都是對象:除了undefined,一切都應是對象。javascript引入兩套類型機制,基本類型和對象類型,number,boolean,string數據類型能夠經過包裝類的方式變成對象數據類型
- javaScript的根對象是Object.prototype對象,Object.type對象是一個空對象,javascript建立每一個對象,實際都是從它克隆來的
- 要獲得一個對象,不是經過實例化,而是找到一個對象做爲原型並克隆它
- javaScript中沒有類的概念,javaScript函數能夠做爲普通函數被調用也能夠做爲構造器被調用,用new運算符來調用時,此時的函數是構造器
- new運算符建立對象的過程是先克隆Object.prototype對象,再進行其餘額外操做(爲了性能,並非每次都新克隆對象),過程:先克隆一個對象,取得外部傳入的構造器,將對象指向正確的原型,借用外部傳入的構造器給obj設置屬性,確保是對象並將對象返回
- 對象會記住它的原型
- 仔細的說是記住對象的構造器的原型,把請求委託給構造器的原型
- __proto__指向該對象的構造器的原型
- 若是對象沒法響應某個請求,他會把這個請求委託給它的構造器的原型
-
原型繼承的將來編程
設計模式是對語言不足的補充,Object.create()
是原型模式的自然實現,使用它完成原型繼承更能體現原型繼承的精髓,可是Object.create()
建立對象的效率並不高,比構造函數要慢,經過設置構造器的prototype來實現原型繼承的時候,除了跟對象外,任何對象都會有一個原型,而經過Object.create(null)
能夠建立出沒有原型的對象設計模式
- 原型模式是一個設計模式,也是一種編程範型,構成了javaScript語言的根本,原型模式十分重要,經過原型模式來實現面向對象系統簡單而強大
第二章、this,call,apply
-
this數組
- this的指向:
- 做爲對象的方法調用
- 做爲普通函數調用
- 構造器調用
- Function.prototype.call或Function.prototype.apply調用
- 做爲對象的方法調用:this指向該對象
var obj={ a;1, getA:function(){ alert(this===obj)
- 做爲普通函數調用:this不做爲對象的屬性被調用時,普通函數方式時,此時this總指向全局對象,window
window.name='globalName' var myObj={ name:'even', getName:function(){ return this.name } } var getName=myObj.getName; console.log(getName())
- 構造器調用:javaScript中沒有類,可是能夠從函數構造器中建立對象,也提供了new,使構造函數更像一個類,構造函數和普通函數的區別就是調用方式,用new運算符調用函數時,該函數總會返回一個對象,構造器裏的this就指向返回的這個函數,除非構造器顯示地返回了一個object類型的對象
4.Function.prototype.call或Function.prototype,apply調用瀏覽器
丟失的this安全
-
call和apply閉包
- 區別:做用如出一轍,區別僅在於傳入參數形式不一樣,第一個函數指定了函數體this對象的指向,第二個參數爲一個帶下標的集合,能夠是數組,也能夠是類數組,javaScript參數在內部就是一個數組來表示,apply比call的使用率更高,call是包裝在apply上面的一層語法糖
- 用途:
- 改變this指向
- Function.prototype.bind
- 借用其餘對象的方
第三章、閉包和高階函數
JavaScript是一門面向對象的編程語言,可是這門語言同時也擁有許多函數式語言的特性 函數式語言的鼻祖是LISP,JavaScript之初參考了Scheme 許多設計模式都是用閉包和高階函數實現的
1.閉包
- 變量的做用域:變量的做用域指變量的有效範圍,聲明變量,若是變量前面沒有帶var,就是全局變量
var a=1; var fun1=function(){ var b=2; var fun2=function(){ var c=3; alert(b);
-
變量的生存週期app
- 對於全局變量,生存週期是永久的,除非主動銷燬這個變量,對於由var 聲明的局部變量,會隨着函數調用的結束而被銷燬。】
var func=function(){ var a=1; return function(){ a++; alert(a); } } var f=func(); f()
-
閉包的更多做用編程語言
- 封裝變量
- 閉包能夠幫助把一些不須要暴露在全局的變量封裝成"私有變量",避免這個變量在其餘地方被修改形成錯誤
- 提煉函數是代碼重構的技巧,經常把可以獨立出來的代碼封裝在獨立的小函數裏,若是小函數不須要複用,最好用閉包將其封閉起來
- 延續局部變量的壽命
var report=(function(){ var imgs=[]; return function(src){ var img=new Image(); imgs.push(img); img.src=src; } })();
-
閉包和麪向對象設計
- 過程與數據的結合是形容面向對象中的「對象」常用的表達
- 對象以方法的形式包含了過程,閉包是在過程當中以環境的形式包含了數據,一般用面向對象能夠實現的功能,閉包也能夠實現
-
用閉包實現命令模式
- 命令模式的意圖是把請求封裝爲對象,從而分離請求的發起者和請求的接收者。
-
閉包與內存管理
- 閉包是一個很是大的特性,但有不少誤解
- 閉包容易形成循環引用,若是此時做用域鏈中保存着DOM節點,就有可能形成內存泄露,這並非閉包和瀏覽器的問題,也不是JavaScript的問題,因爲BOM和DOM中的對象是使用C++以COM實現,COM對象的垃圾回收機制採用的是引用計數,若是兩個對象之間造成了循環引用,那麼兩個對象就都不能被回收,本質上不是閉包形成的。
- 解決:把循環引用中的變量設爲null,設置爲null表示切斷與它此前引用的值的聯繫
2.高階函數
高階函數:函數能夠做爲參數被傳遞,函數能夠做爲返回值輸出
- 函數做爲參數傳遞
- 回調函數
- Array.prototype.sort
- 函數做爲返回值輸出
- 高階函數實現AOP(面向切面編程)
- 面向切面編程的主要做用是把一些跟核心業務無關的功能抽離出來,例如日誌統計,安全控制,異常處理等,抽離出來後經過動態織入的方式摻入業務邏輯中,好處是能夠保持業務邏輯模塊的純淨和高內聚性,其次是能夠很方便的複用日誌統計等模塊兒
- 高階函數的其餘應用
- currying
- uncurrying
- 函數節流
- 分時函數
- 惰性加載函數
注:本篇博客主要內容來自書籍原文