JS面向對象篇1、理解對象及屬性特性(屬性描述符)

本文內容
一、理解對象;
二、ECMAScript有兩種屬性類型:數據屬性和訪問器屬性(getter和setter函數);
三、數據屬性的屬性特性:[[Configurable]]、[[Enumerable]]、[[Writable]]、[[value]];
四、訪問器屬性的屬性特性:[[Configurable]]、[[Enumerable]]、[[get]]、[[set]];
五、Object.defineProperty()、Object.defineProperties()、Object.getOwnPropertyDescriptor()設置或讀取屬性特性(屬性描述符)的方法javascript

理解對象

ECMA-262把對象定義爲:無序屬性的集合,其屬性能夠包含基本值、對象或者函數。
也就是說對象是一組沒有特定順序的名值對,一個名字對應一個值,值能夠是數據(包括基本值以及引用類型值)和函數,每個名值對都是這個對象的屬性。java

var person = {
name: 'youyang',
age: 25,
job: 'coder',
sayName: function() {
console.log(this.name)
}
}

以上代碼建立了一名爲person的對象,它有四個屬性:name、age、job和sayName。注意雖然一般咱們說name、age、job爲屬性,而sayName稱做person對象的方法,其實它也是屬性,只不過值爲函數而已。框架

屬性類型及屬性特性

一、首先須要明確javascript對象中有哪些屬性類型?

ECMAScript中有兩種屬性:數據屬性和訪問器屬性。函數

二、什麼是屬性特性?

每一個對象的屬性(包括方法)在建立時都帶有一些特徵值,ECMA-262定義這些特性值是爲了實現javascript引擎用的,即內部使用的,因此該規範把它們放在兩對方括號中:如[[Enumerable]]。this

三、那麼屬性都有哪些描述行爲的特性呢?不一樣的屬性類型的屬性特性又有什麼不一樣呢?

數據屬性

數據屬性有四個描述其行爲的特性:code

  1. [[configurable]]:表示可否經過delete關鍵字刪除屬性從而從新定義屬性,可否修改屬性的特性(包括[[configurable]]特性自己以及下面三個其餘特性),或者可否把屬性修改成訪問器屬性。像上面例子中那樣直接定義在對象上的屬性默認值爲true.
  2. [[Enumerable]]:是否可枚舉(for-in循環中可否返回該屬性),上面那樣直接定義在對象上的屬性默認值爲true。
  3. [[Writable]]:是否可修改屬性的值,默認爲true;
  4. [[value]]:對應屬性值,讀取的時候從這裏讀取,寫入的時候將新值保存在這裏,默認值爲undefined;
var obj = {
num: 10
}

這裏建立了一個名爲num的屬性,它的 [[configurable]]、 [[Enumerable]]、 [[Writable]]均爲true,而[[value]]爲10。對象

訪問器屬性

相比數據屬性,訪問器屬性沒有[[value]]這一屬性特性,而是擁有一對函數:getter()和setter(),在讀取訪問器屬性的時候,調用getter(),該函數負責返回有效的值,在寫入即設置屬性的值的時候調用setter()並傳入新值,由setter()負責執行處理數據的操做。ip

訪問器屬性包含4個屬性特性:開發

  1. [[configurable]]:表示可否經過delete刪除屬性,可否修改屬性的特性(包括[[configurable]]特性自己以及下面三個其餘特性),或者可否把屬性修改成數據屬性。直接定義在對象上的屬性默認值爲true;
  2. [[Enumerable]]:是否可枚舉(for-in循環中可否返回該屬性),上面那樣直接定義在對象上的屬性默認值爲true;
  3. [[Get]]:在讀取屬性時調用的函數,默認爲undefined;
  4. [[Set]]:在寫入屬性時調用的函數,默認爲undefined。

Object.defineProperty()

這個方法有兩個做用,一個是修改屬性的默認屬性特性,另外一個就是定義屬性,由於若是你想在定義一個屬性的同時指定它的一些屬性特性那麼就必須使用這個方法,而且當你想定義一個訪問器屬性時只能使用Object.defineProperty()來實現,由於訪問器屬性是不能直接定義的。
此方法接收的參數:對象,指定的屬性名稱,一個描述符對象(用來設置屬性特性的對象)
使用方法以下:
一、要修改一個屬性的默認特性get

var obj = {
num: 10
}
Object.defineProperty(obj, 'num', {
value: 20,
writable: false
})
console.log(obj.num) // 20
obj.num = 30
console.log(obj.num) // 20

上面的例子中,咱們將對象obj的屬性num的[[writable]]是否可修改特性設置爲了false,因而num屬性不能被修改,當嘗試爲它寫入新值(obj.num = 30)時,非嚴格模式下,此操做會被忽略,嚴格模式下則會報錯。

二、定義訪問器屬性
訪問器屬性不能直接定義,必須使用Object.defineProperty()。

var obj = {
num: 10
}
Object.defineProperty(obj, 'data', {
get: function() {
return this.num
},
set: function(newVal) {
if (newVal > 10) {
this.num = newVal
}
}
})
console.log(obj.data) // 10
obj.data = 20
console.log(obj.data) // 20
console.log(obj.num) // 20

getter和setter函數或許你常據說,可是並不知道它們究竟是什麼,由於咱們確實在平常開發中不多有機會用到它們,可是在一些框架的源碼中常見到它們的應用。

Object.defineProperties()

與Object.defineProperty()方法相同,Object.defineProperties()方法也有一樣做用:設置和修改屬性特性,只不過Object.defineProperties()方法能夠設置多個屬性。
使用方法以下:

var obj = {
num: 10
}
Object.defineProperties(obj, {
name: {
writable: false,
value: '張三'
},
data: {
get: function () {
return this.num
},
set: function (newVal) {
if (newVal > 10) {
this.num = newVal
}
} 
}
})

以上代碼使用Object.defineProperties()定義了一個數據屬性和一個訪問器屬性。

Object.getOwnPropertyDescriptor()

這個方法的做用就是獲取指定屬性的屬性描述符,所謂屬性描述符就是咱們以前一直提到的屬性特性。
接收兩個參數:屬性所在對象和指定屬性名稱
返回值:一個對象,若是是訪問器屬性,對象的屬性包括:configurable,enumerable,get和set,若是是數據屬性,則返回的這個對象的屬性有:configurable,enumerable,writable,value。

var obj = {
num: 10
}
console.log(Object.getOwnPropertyDescriptor(obj, 'num')) // {value: 10, writable: true, enumerable: true, configurable: true}
相關文章
相關標籤/搜索