javascript中對象由key和value組成,key是標識符,value可以為任意類型
創建對象的方式
1、通過構造函數
var obj = new Object()
obj.name = 'alice'
obj.age = 18
2、通過字面量
var obj = {
name: 'alice',
age: 18
}
屬性描述符
對屬性進行精準的操作,比如定義屬性是否可被刪除、遍歷或修改
1、語法
//定義一個屬性
Object.defineProperty(Object, PropertyKey, attributes)
// 定義多個屬性
Object.defineProperties(Object, properties)
2、屬性描述符特徵
| 屬性 | 描述 | 通過對象定義時默認值 | 通過屬性描述符定義時默認值 |
|---|---|---|---|
| configurable | 定義屬性是否可被刪除、重新定義 | true | false |
| enumerable | 定義屬性是否可被枚舉,如通過for in/Object.keys | true | false |
| writable | 是否可被修改 | true | false |
| value | 讀取屬性和修改的時候操作的值 | undefined | undefined |
| get | 獲取屬性時會執行的函數 | undefined | undefined |
| set | 設置屬性時會執行的函數 | undefined | undefined |
3、屬性描述符的分類
屬性描述符分為數據屬性描述符和讀取屬性描述符,數據屬性描述符用來定義屬性,讀取屬性描述符用於為函數中不願意暴露的屬性來進行讀取和設置的操作
不同屬性描述符可操作的屬性也不一樣
| 分類 | configurable | enumerable | writable | value | get | set |
|---|---|---|---|---|---|---|
| 數據屬性描述符 | √ | √ | √ | √ | × | × |
| 存取屬性描述符 | √ | √ | × | × | √ | √ |
4、定義
給obj對象添加skill屬性,屬性的描述為不可刪除或重新定義、不可修改、可枚舉
var obj = {
name: 'alice',
age: 18
}
Object.defineProperty(obj, 'skill', {
configurable: false,
writable: false,
enumerable: true,
value: 'flying',
})
console.log(obj)
delete obj.skill
console.log(obj)
obj.skill = 'swimming'
console.log(obj)
所以上面刪除和修改都是無效的操作,執行結果如下
對象的其它方法
1、獲取對象的屬性描述符
- getOwnPropertyDescriptor
- getOwnPropertyDescriptors
2、操作屬性
- preventExtensions 禁止新增屬性
- seal 封閉屬性,即禁止新增、刪除屬性
- freeze 凍結屬性,即禁止新增、修改、刪除屬性
3、查詢屬性
- isExtensible 查詢是否可新增屬性
- isSealed 查詢是否是封閉的屬性
- isFrozen 查詢是否是凍結的屬性
var user = {
name: 'kiki',
age: 18
}
console.log('getOwnPropertyDescriptor', Object.getOwnPropertyDescriptor(user, 'name'))
console.log('getOwnPropertyDescriptors', Object.getOwnPropertyDescriptors(user))
Object.preventExtensions(user)
console.log('isExtensible', Object.isExtensible(user))
user.skill = 'flying'
console.log('user', user)
Object.seal(user)
console.log('isSealed', Object.isSealed(user))
delete user.age
console.log('user', user)
Object.freeze(user)
console.log('isFrozen', Object.isFrozen(user))
user.name = 'alice'
console.log(user)
以上代碼執行結果如下
原型
1、隱式原型
每一個對象都有隱式原型,可通過Object.getPrototypeOf或者__proto__(存在瀏覽器兼容問題)獲取,查找元素時,如果自身對象沒有,會向原型上查找
var obj = {}
console.log(obj.__proto__)
console.log(Object.getPrototypeOf(obj))
console.log(obj.name)
obj.__proto__.name = 'alice'
console.log(obj.name)
對象的隱式原型指向空對象
2、顯式原型
每個函數除了有隱式原型,還有顯式原型prototype,prototype中有一個屬性constructor指向函數自己
function foo(){}
console.log(foo.__proto__)
console.log(foo.prototype)
console.log(Object.getOwnPropertyDescriptors(foo.prototype))
構造函數
在構造函數中,通過new關鍵字可以批量創建對象
1、定義方式
function foo()
var f = new foo()
2、new關鍵字的操作
- 在內存中創建一個新對象(空對象)
- 對象的__proto__屬性被賦值為構造函數的prototype屬性
- 構造函數的this,將指向創建的對象
- 執行構造函數的代碼
- 如果函數沒有返回非空對象,則返回創建的新對象
3、在內存中的表現
new關鍵字會將創建的對象的__proto__屬性賦值為構造函數的prototype屬性
function Person(){}
var p1 = new Person()
var p2 = new Person()
console.log(p1.__proto__ === Person.prototype) // true
console.log(p1.__proto__ === p2.__proto__) // true
圖示如下
以上就是面向對象編程的部分內容,下一篇記錄js中實現繼承的方式,關於js高級,還有很多需要開發者掌握的地方,可以看看我寫的其他博文,持續更新中~