前言
權威指南中摘要的,工作中用不到的,重要的js基礎。
三類對象兩類屬性
內置對象(native object) 是由ECMScript規范定義的對象或者類。例如:函數,數組,日期,正則...
宿主對象(host object) 是由js編譯器所嵌入的宿主環境(web瀏覽器)所定義的。比如客戶端js中表示網頁結構的HTMLElement對象就是宿主環境創建的對象。宿主環境定義的對象可以直接使用的話,我們也可以把它們當做內置對象。
自定義對象(user-defined object) 由運行中的js創建的對象。
自有屬性(own property) 直接在對象當中定義的屬性,區別於繼承屬性。
繼承屬性(inherited property) 在對象原型中定義的屬性。
屬性描述符對象
ES5中定義了一個屬性描述符對象(property descriptor)。這個對象屬性和他們所描述的屬性特性是同名的。
value:屬性的值值。
writable:可寫性,是否可以設置值。
enumerable:可枚舉性,遍歷對象時該屬性會不會出現。
configurable:可配置性。
作為屬性特性的存取器
對象屬性是由名字和值跟一組屬性特性構成的,屬性值可以用一個或兩個方法進行替代,這兩個方法就是getter和setter定義的屬性特性。由getter和setter定義的屬性叫做“存取器屬性”。
存取器屬性的特點:
1,當程序查詢存取器屬性值時,js調用getter方法。這個方法返回的就是屬性存取表單式的值。
2,當程序設置存取器屬性值是,js調用setter方法。這個方法將賦值表達式右邊的計算結果,傳入setter。
3,存取器屬性不具有可寫性,如果同時具有getter和setter方法那它就是一個讀寫屬性。也可以只擁有其中一個,來作為只讀或者只寫屬性。
定義存取器屬性
var o = { // 普通的數據屬性
data:null; // 存取器屬性
set ODate(value){ this.data = value; // 處理復制表達式右側計算結果(value)的屬性設置表達式
}, get ODate(){ return this.data; // 屬性返回表達式
} } // 設置data,獲取data
o.OData = {id:0}; o.OData; =>{id:0}
獲取自有屬性的屬性描述符對象Object.getOwnPropertyDescriptor()
// 當我們為對象創建屬性時如果沒有指定屬性描述符,那就都是默認的 可枚舉,可配置,可讀寫,
var obj = { name:"小花" } console.log(Object.getOwnPropertyDescriptor(obj,"name"));
定義屬性描述符對象Object.defineProperty(obj,attributeName,PropertyDescriptor)
// 定義cat的name屬性為不可枚舉(此后使用for in 遍歷對象屬性時,name不會出現),value為小花 var cat = {}; Object.defineProrerty(cat , "name",{ value:"小花", enumerable:false })
同時定義或修改對象的多個屬性及其描述符Object.defineProperties()
// 參數一是目標對象,參數二是屬性為鍵描述符為值的對象
var cat = Object.defineProperties({},{ name:{value:"小花"}, age:{value:6}, // 值為大菊,不可寫
type:{value:"大菊",writable:false}, // 存取器特性替代屬性值value,不可枚舉
date:{ get:function(){return [this.name,this.age]}, enumerable:false } })
使用屬性描述符實現jq中$.extend方法的部分功能:
1,給根對象Object的原型拓展一個extend方法。
2,接收要復制的目標對象,將他的屬性和屬性特性復制到調用對象。
3,復制規則:存在同名屬性時保留原有屬性,復制目標對象上的一切可枚舉自有屬性。
Object.defineproperty(Object.prototype,"extend",{ enumerable:false, value:function(o){ // 得到O對象的所有自有屬性名稱列表
var proNames = Object.getOwnPropertyNames(o); // 排除已存在屬性
for(var i = 0; i < proNames.length; i++){ if(proNames[i] in this) continue; // 獲取該屬性的屬性描述符對象
var desc = Object.getOwnpropertyDescriptor(o,proName[i]); // 將屬性copy到調用對象
Object.defineProperty(this,proName[i],desc); } } })
小結:
》三類對象:內置對象,宿主對象,自定義對象。
》兩類屬性:自有屬性,繼承屬性。
》存取器屬性:區別於數據屬性,屬性名稱就是getter、setter方法名稱。
》屬性每個屬性都擁有屬性描述符對象,不顯示定義屬性的描述符對象時,他們默認都是可讀寫,可枚舉,可配置的。
》ES5提供了兩個API用來定義或修改屬性及其描述符:
獲取指定對象指定屬性的屬性描述符對象:Object.getOwnPropertyDescriptor()
同時定義多個屬性及其描述符:Object.defineProperties()
定義單個屬性及其描述符:Object.defineProperty(obj,attributeName,PropertyDescriptor)
》js中的普通對象能夠從根對象上繼承到它提供的屬性方法。我們基於這個特性為根對象創建了一個extend方法可以用來復制其他對象上的自有可枚舉屬性。