javascript
《JS权威指南学习总结--6.7属性的特性》
內(nèi)容要點:
一.ES5中查詢和設(shè)置屬性的API
????? 1.可以通過這些API給原型對象添加方法,并將它們設(shè)置成不可枚舉的,這讓它們看起來更像內(nèi)置方法。
????? 2.可以通過這些API給對象定義不能修改或刪除的屬性,借此 "鎖定" 這個對象。
????? 3.數(shù)據(jù)屬性的4個特性: 值(value)、可寫性(writable)、可枚舉性(enumerable)和可配置性(configurable)。
????? 4.存取器屬性不具有值特性和可寫性,它們的可寫性是由setter方法存在與否決定的。因此存取器屬性的4個特性是:讀取(get)、寫入(set)、可枚舉性(numberable)和可配置性(configurable)。
????? 其中writable、enumerable和configurable都是布爾值,當然,get屬性和set屬性是函數(shù)值。
二.Object.getOwnPropertyDescriptor()
????? 1.通過調(diào)用Object.getOwnPropertyDescriptor()可以獲得某個對象特定屬性的屬性描述符:
????? 例如:
???????? //返回{ value : 1,writable : true,enumerable:true,configurable:true }
???????? Object.getOwnPropertyDescriptor({x:1},"x");
??????? //查詢上文中定義的random對象的octet屬性
??????? //返回{get:/*func*/,set:undefined,enumerable:true,configurable:true}
?????? Object.getOwmPropertyDescriptor(random,"octet");
?????? //對于繼承屬性和不存在的屬性,返回undefined
??????? Object.getOwnPropertyDescriptor({},"x"); //undefined,沒有這個屬性
????? ? Object.getOwnPropertyDescriptor({},"toString"); //undefined,繼承屬性
????? ? Object.getOwnPropertyDescriptor()只能得到自有屬性的描述符。要想獲得繼承屬性的特性,需要遍歷原型鏈
三.Object.definePeoperty()
?????? 傳入要修改的對象,要創(chuàng)建或修改的屬性的名稱以及屬性描述符對象。
?????? var o = {}; //創(chuàng)建一個空對象
?????? //添加一個不可枚舉的數(shù)據(jù)屬性x,并賦值為1
??????? Object.defineProperty(o,"x",{value:1,writable:true,enumerable:false,configurable:true});
????? //屬性是存在的,但不可枚舉
??????? o.x; //=>1
???????? Object.keys(o) //=>[]
????? //現(xiàn)在對屬性x做修改,讓它變?yōu)橹蛔x
??????? Object.defineProperty(o,"x",{writable:false});
???? //試圖更改這個屬性的值
?????? o.x = 2; //操作失敗但不報錯,而在嚴格模式中拋出類型錯誤異常
?????? o.x=1;
????? //屬性依然是可配置的,因此可以通過這種方式對它進行修改
??????? Object.defineProperty(o,"x",{value:2});
??????? o.x //=>2
????? //現(xiàn)在將x從數(shù)據(jù)屬性修改為存取器屬性
?????? Object.defineProperty(o,"x",{get:function(){return 0;}});
?????? o.x //=>0
????? 傳入Object.defineProperty()的屬性描述符對象不必包含所有4個特性。對于新創(chuàng)建的屬性來說,默認的特性值是false或undefined。對于修改的已有屬性來說,默認的特性值沒有做任何修改。注意:這個方法要么修改已有屬性要么新建自有屬性,但不能修改繼承屬性。
四.Object.defineProperties()
?????? 同時修改或創(chuàng)建多個屬性。第一個參數(shù)是要修改的對象,第二個參數(shù)是一個映射表,它包含要新建或修改的屬性的名稱,以及它們的屬性描述符
?????? 例如:
?????? var p = Object.defineProperties({},{
????????????? x:{value:1,writable:true,enumerable:true,configurable:true},
????????????? y:{value:1,writable:true,enumerable:true,configurable:true},
????????????? r:{??
??????????????????? get:function(){ return Math.sqrt(this.x*this.x+this.y*this.y) },
???????????????????? enumerable:true,
???????????????????? configurable:true
????????????????? }
?????? ? });
???????? 這段代碼從一個空對象開始,然后給它添加了兩個數(shù)據(jù)屬性和一個只讀存儲器屬性,最終Object.defineProperties()返回修改后的對象
五.
?? ?? 對于那些不允許創(chuàng)建或修改的屬性來說,如果用Object.defineProperty()和Object.defineProperties()返回修改后的對象(新建或修改)就會拋出類型錯誤異常,
????? 比如,給一個不可擴展的對象新增屬性就會拋出類型錯誤異常。造成這些方法拋出類型錯誤異常的其他原因則和特性本身相關(guān)。
????? 可寫性控制著特性的修改,可配置性控制著對其他特性的(包括屬性是否可以刪除)的修改。然而規(guī)則遠不止這么簡單:
????? 例如,如果屬性是可配置的話,則可以修改不可寫屬性的值。同樣,如果屬性是不可配置的,仍然可以將可寫屬性修改為不可寫屬性。
????? 下面是完整的規(guī)則,任何對Object.defineProperty()或Object.defineProperties()違反規(guī)則的使用都會拋出類型錯誤異常
??????????? 1.如果對象是不可擴展的,則可以編輯已有的自有屬性,但不能給它添加新屬性
??????????? 2.如果屬性是不可配置的,則不能修改它的可配置性和可枚舉性。
??????????? 3.如果存取器屬性是不可配置的,則不能修改其getter和setter方法,也不能將它轉(zhuǎn)換為數(shù)據(jù)屬性
??????????? 4.如果數(shù)據(jù)屬性是不可配置的,則不能將它轉(zhuǎn)換為存取器屬性
??????????? 5.如果數(shù)據(jù)屬性是不可配置的,則不能將它的可寫性從false修改為true,但可以從true修改為false。
??????????? 6.如果數(shù)據(jù)屬性是不可配置的且不可寫的,則不能修改它的值。然而可配置但不可寫屬性的值是可以修改的(實際上是先將它標記為可寫的,然后修改它的值,最后轉(zhuǎn)換為不可寫的)
六.
? ? 上節(jié)中實現(xiàn)了extend()函數(shù),這個函數(shù)把一個對象的屬性復制到另一個對象中。這個函數(shù)只是簡單地復制屬性名和值,沒有復制屬性的特性,而且也沒有復制存取器屬性的getter和setter方法,只是將它們簡單地轉(zhuǎn)換為靜態(tài)的數(shù)據(jù)屬性。
? ?? 下例給出了改進的extend(),它使用Object.getOwnPropertyDescriptor()和Object.defineProperty()對屬性的所有特性進行復制。新的extend()作為不可枚舉屬性添加到Object.prototype中,因此它是Object上定義的新方法,而不是獨立的函數(shù)。
? ? ? /*給Object.prototype添加一個不可枚舉的extend()方法?
? ? ?? *這個方法繼承自調(diào)用它的對象,將作為參數(shù)傳入的對象的屬性一一復制
? ? ?? *除了值之外,也復制屬性的所有特性,除非在目標對象中存在同名的屬性
? ? ?? *參數(shù)對象的所有自有對象(包括不可枚舉的屬性)也會一一復制 ?????
?????? */? ??
?????? Object.defineProperty(Object.prototype,
????????? "extend",
????????? {
????????????? writable: true,
????????????? enumerable:false,????????????? //將其定義為不可枚舉的
????????????? configurable:true,
????????????? value:function(o){??????????? //值就是這個函數(shù)
??????????????????? //得到所有的自有屬性,包括不可枚舉屬性
??????????????????? var names = Object.getOwnPropertyNames(o);
??????????????????? //遍歷它們
??????????????????? for(var i = 0; i <names.length; i++){
????????????????????????? //如果屬性已經(jīng)存在,則跳過
????????????????????????? if(names[i] in this) continue;
???????????????????????? //獲得o中的屬性的描述符
???????????????????????? var desc = Object.getOwnPropertyDescriptor(o,names[i]);
???????????????????????? //用它給this創(chuàng)建一個屬性
???????????????????????? Object.defineProperty(this,names[i],desc);
????????????????? }
????????????? }
?????? });
?
轉(zhuǎn)載于:https://www.cnblogs.com/hanxuming/p/5795441.html
總結(jié)
以上是生活随笔為你收集整理的《JS权威指南学习总结--6.7属性的特性》的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第02天
- 下一篇: PHP 函数截图 哈哈哈