屬性類型
數據屬性
[[Configurable]]
:表示能否通過delete刪除屬性,能否修改屬性特性,能否把屬性修改爲訪問器屬性。
[[Enumerable]]
:表示能否通過for-in循環返回屬性。
[[Writable]]
:表示是否能修改屬性值。
[[Value]]
:包含這個屬性的數據值,默認值爲undefined
。
當直接在對象上定義屬性時(即var Person={name:'Joker'}
),前三個屬性都默認爲true
。
修改屬性默認的特性的方法——Object.defineProperty()
在調用Object.defineProperty()方法創建一個新的屬性時,如果不指定considerable
,innumerable
和writeable
特性的默認值都是false
。當只是修改一個已定義的屬性的特性時,無此限制。
一旦把屬性的considerable
定義爲false
,即,把屬性定義爲不可配置的,則不能變回可配置了,且修改除writable
之外的屬性都會發生錯誤。
var Person = {}
Object.defineProperty(person, 'name', {
value: 'Joker', //如果不指定那三個屬性,則都默認爲false
})
// 'use strict' //聲明爲嚴格模式
person.name = 'rewrite' // 在嚴格模式下會報錯,在非嚴格模式下下會忽略該語句
在非嚴格模式下,修改已設置writable
爲false
的屬性的值,賦值操作將會被忽略;在嚴格模式下,將拋出錯誤。
var person = {
name: 'defaultname',
}
Object.defineProperty(person, 'name', {
writable: false, //設置name屬性爲不可修改
})
person.name = 'rewrite1' //重寫失敗,在非嚴格模式下會忽略,嚴格模式下會報錯
console.log(person1.name) //defaultname
Object.defineProperty(person1, 'name', {
writable: true, //重新設置name屬性爲可修改
})
person1.name = 'rewrite2' //可以修改
console.log(person1.name) //rewrite2
訪問器屬性
包含getter
和setter
函數。在讀取訪問器屬性時,會調用get
函數負責返回有效的值;在寫入訪問期屬性時會調用set
函數並傳入新值,負責如何處理數據。
通過Object.defineProperty()
來定義。
使用訪問器屬性的常見方式是,設置一個屬性的值會導致其他屬性發生變化,如下:
var book = {
year: 2000,
edition: 1,
}
Object.defineProperty(book, 'year', {
get: function () {
return this.year
},
set: function (newValue) {
if (newValue >= 2000) { // 改變year的同時改變edition
this.edition = Math.floor((newValue - 2000) / 3) + 1
}
},
})
book.year = 2001
console.log(book.edition) // 1
book.year = 2010
console.log(book.edition) // 4
只指定getter
意味着屬性不可寫,非嚴格模式下,嘗試寫入會被忽略,嚴格模式下,會拋出錯誤。
只指定setter
意味着屬性不可讀,非嚴格模式下,會返回undefined
,嚴格模式下,會拋出錯誤。
讀取屬性的特性
var person = {}
Object.defineProperty(person, 'name', {
enumerable: false,
value: 'name',
})
// 讀取屬性的特性
var descriptor = Object.getOwnPropertyDescriptor(person, 'name')
console.log(descriptor.enumerable) //false
console.log(descriptor.value) //name
判斷是否包含某屬性和in操作符
.hasOwnProperty()
用於檢測一個屬性存在於實例中,還是在原型中。當存在於實例中時返回true。
function Person() {}
Person.prototype.name = 'defaultName' //添加一個原型屬性
person.job = 'instanceJob' //添加一個實例屬性
console.log(person.hasOwnProperty('job')) // true
console.log(person.hasOwnProperty('name')) // false
in操作符
:檢測屬性是否在實例或原型中,只要包括,就爲true。
console.log('name' in person1) // true
console.log('job' in person1) // true
結合in操作符和hasOwnProperty()可以判斷一個屬性是實例屬性還是原型屬性
function hasPrototypeProperty(obj, name) {
return !obj.hasOwnProperty(name) && name in obj
}
console.log(hasPrototypeProperty(person, 'name')) // true
console.log(hasPrototypeProperty(person, 'job')) // false
獲取屬性
for-in——所有枚舉屬性
// 現在person實例有實例屬性name、sayName,原型屬性job、sayJob
for (let prop in person1) {
console.log(prop) //所有實例屬性、原型屬性
}
被設置爲不可枚舉,即emunerable爲false的屬性在for…in中不會被訪問到。
function Person() {}
//定義原型屬性,其中一個在後面被設置爲不可枚舉
Person.prototype.protoNameEmun = 'protoNameEmun'
Person.prototype.protoNameUnemun = 'protoNameUnemun'
Person.prototype.protoSayName = function () {}
var person = new Person()
//定義實例屬性,其中一個在後面被設置爲不可枚舉
person.instanceNameEmun = 'instanceNameEmun'
person.instanceNameUnemun = 'instanceNameUnemun'
person.instanceSayName = function () {}
// 定義爲不可枚舉
Object.defineProperties(person, {
protoNameUnemun: {
enumerable: false,
},
instanceNameUnemun: {
enumerable: false,
},
})
// 輸出實例屬性、原型屬性中所有可枚舉的,不可枚舉的不輸出
// 輸出:instanceNameEmun、instanceSayName、protoNameEmun、protoSayName
for (let prop in person) {
console.log(prop)
}
Object.keys()——可枚舉實例屬性的字符串數組
Object.keys()
方法這個方法接收一個對象作爲參數,返回一個包含所有可枚舉的實例屬性的字符串數組。
同樣,對於上述的例子:
var key1 = Object.keys(Person.prototype)
var key2 = Object.keys(person)
console.log(key1) //[ 'protoNameEmun', 'protoNameUnemun', 'protoSayName' ]
console.log(key2) //[ 'instanceNameEmun', 'instanceSayName' ]
Object.getOwnPropertyNames()——所有實例屬性的字符串數組
返回包含所有實例屬性(不論是否可以枚舉)的字符串數組。
var names1 = Object.getOwnPropertyNames(Person.prototype)
var names2 = Object.getOwnPropertyNames(person)
console.log(names1)
// [ 'constructor', 'protoNameEmun', 'protoNameUnemun', 'protoSayName' ]
console.log(names2)
// [ 'instanceNameEmun', 'instanceNameUnemun', 'instanceSayName', 'protoNameUnemun' ]
注意在name1中包含了不可枚舉屬性constructor,正說明了“不論是否可以枚舉”這一點。