javascript
重学《JavaScript 高级程序设计》笔记 第6章对象
第6章 面向對象的程序設計
ECMAScript中沒有類的概念;
1.創建對象-歷史
1.1 創建實例,添加方法和屬性 → 對象字面量
缺點: 使用同一接口創建很多對象,產生大量重復代碼
var person = new Object() person.name = "Y" person.age = 18 person.job = "police"person.sayName = function() {alert(this.name) }↓
var person = {name = "Y",age = 18,job = "police",sayName = function() {alert(this.name)} }1.2 工廠模式 (返回對象)
缺點: 沒有解決對象識別的問題:怎樣知道一個對象的類型;
特點: 內部創建對象,并返回
1.3 構造函數模式
缺點: 每個方法都要在每個實例上重新創建一遍!不同實例上的同名函數是不相等的,然而,創建2個完成同樣任務的Function實例的確沒有必要。
特點:
沒有顯示創建對象;
沒有return;
將方法屬性賦值給this對象;
首字母大寫;
構造函數創建的實例標識為一種特定的類型
1.3.1 理解面試題
調用構造函數創建對象,實際會經歷以下4個步驟:
- 在全局作用域調用函數,this總是指向GLOBAL對象
1.3.2 將構造函數當做函數
任何函數,只要通過new操作符來調用,便可以作為構造函數;若不用,即與普通函數無異。this會指向Global對象(在瀏覽器中就是window)
1.3.3 將方法定義到構造函數外部
缺點: 在全局作用域上定義的函數,若只能被某個對象調用,不合理;并且,如果對象需要定義很多方法,則需要定義很多個全局函數,對于這個自定義的引用類型就絲毫沒有封裝性可言。
function Person(name, age, job) {this.name = namethis.age = agethis.job = job } function sayName() {alert(this.name) }1.4 原型模式
1.4.1 理解原型模式
function Person() {} Person.prototype.name = "Y" Person.prototype.age = 18 Person.prototype.job = "police" Person.prototype.sayName = function () {alert(this.name) }1.4.2 in操作符
in操作符會在通過對象能訪問給定屬性時返回true,無論屬性存在于實例還是原型中
"name" in p1 // true1.4.3 確認屬性存在于原型
function hasPrototypeProperty(object,name) {return !object.hasOwnProperty(name) && (name in object) }1.4.4 更簡單的原型語法
缺點: constructor屬性不再指向Person,切斷了實例和原型對象的聯系;對包含引用類型值的屬性,被實例共享會造成問題。
特點: 減少不必要的輸入(每添加一個屬性/方法就要多敲一遍Person.prototype)
將Person.prototype設置為一個以對象字面量形式創建的新對象,本質上重寫了prototype對象(創建函數時自動創建的原型對象),導致constructor屬性指向Object構造函數,盡管instanceof還能返回正確的結果。
function Person() {} Person.prototype = {name : "Y",age : 18,job : "police",sayName: function () {alert(this.name)} } p1 instanceof Object // true p1 instanceof Person // true p1.constructor == Person // false p1.constructor == Object // true增加constructor屬性,確保該屬性能訪問到適當的值。
function Person() {} Person.prototype = {constructor : Person,name : "Y",age : 18,job : "police",sayName: function () {alert(this.name)} }1.4.5 原生對象的問題
function Person() {} Person.prototype = {constructor : Person,friends:["Yoona","Jessica"], // 數組,引用類型name : "Y",age : 18,job : "police",sayName: function () {alert(this.name)} } p1.friends.push("Krystal") p1.friends == p2.friends1.4.6 組合使用構造函數模式和原型模式
構造函數模式用于定義實例屬性,原型模式用于定義方法和共享的屬性。(實例屬性中的引用類型互不干擾)
function Person(name, age, job) {this.name = namethis.age = agethis.job = jobthis.friends = ["Yoona","Jessica"] }Person.prototype = {constructor : Person,sayName: function () {alert(this.name)} }1.4.7 原生對象的原型
通過原生對象的原型,不僅可以取得所有默認方法的引用,也可以定義新方法。但不推薦在產品化的程序中修改原生對象的原型:
如果因為某個實現中缺少某個方法,就在原始對象的原型中添加,那么當在另一個支持該方法的實現中運行代碼時,就可能會導致命名沖突,而且這樣做也可能會意外地重寫原生方法。
1.5 梳理
1.6 修改原生對象的原型
String.prototype.startsWith = function(){}在當前環境中,所有字符串都可以調用startsWith,但不推薦,可能會產生命名沖突,也可能會意外地重寫原生方法。
String.prototype. toString = function () {console.log('修改原生對象默認方法') }'str'.toString() // 修改原生對象默認方法將原生對象原型指向空,沒效果
String.prototype = null console.log('str'.toString()) // str2. 屬性類型 P139
2.1 數據屬性
- 一旦把屬性定義為不可配置的,就不能再把它變回可配置了;
- 要修改屬性默認的特性,必須使用Object.defineProperty(),3個參數:對象、屬性名、描述符對象(屬性必須是數據屬性),若不指定數據屬性,則默認為false;
2.2 訪問器屬性
1) [[Configurable]]
2) [[Enum而able]]
3) [[Get]]:讀取屬性時默認調用的函數,默認值undefined
4) [[Set]]:寫入屬性時默認調用的函數,默認值undefined
- 屬性 _year 前面的下劃線用于表示只能通過對象方法訪問的屬性;
- 使用訪問器屬性的常見方式:設置一個屬性的值會導致其他屬性發生變化;
2.3 讀取屬性
Object.getOwnPropertyDescriptor(),2個參數:對象、屬性
var descriptor = Object.getOwnPropertyDescriptor(person,"age") alert(age.value) alert(age.enumerable) alert(age.configurable) alert(age.get)方法集合
Object.defineProperty() // 修改屬性默認值 Object.getOwnPropertyDescriptor() //讀取屬性的描述符 誰誰的原型對象.isPrototypeOf(實例) // 參數是實例,判斷實例內部是否有指向構造函數原型對象的指針 hasOwnProperty() // 檢測屬性來自實例(返回true)還是原型3. 繼承(子類繼承父類的特征和行為)
3.1 原型鏈
原型鏈的問題
讓原型對象等于另一個類型的實例。
SubType.prototype = new SuperType()SubType的實例指向SubType的原型,進而又指向SuperType的原型
3.2 默認的原型
所有引用類型默認都繼承了Object,所有函數的默認原型都是Object的實例,因此默認原型都會包含一個內部指針,指向Object.prototype,這也正是所有自定義類型都會繼承toString()、valueOf()等默認方法的根本原因。完整的原型鏈如下:
3.3 組合繼承
4. 方法整理
- A.isPrototypeOf(a)
// 實例a的__proto__指向A的原型
// 判斷原型對象A是否是實例a的原型,是則返回true - a.hasOwnProperty(‘name’) 判斷屬性是否存在于實例中(實例屬性),是則返回true
Object.keys() 獲得對象上所有可枚舉的屬性 - ‘name’ in a 無論原型/實例,只要是能訪問得到的屬性,in操作符返回true(包括constructor)'name’字符串
for-in循環,返回所有能通過對象訪問的、可枚舉的屬性 ,(遍歷一個實例對象,原型上的屬性也會打印、要只打印實例屬性,需要配合hasOwnProperty) - Object.getOwnPropertyNames(),得到所有實例屬性,包括constructor
總結
以上是生活随笔為你收集整理的重学《JavaScript 高级程序设计》笔记 第6章对象的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android数据库 分页查询,Andr
- 下一篇: 《JavaScript 高级程序设计》笔