首頁  >  文章  >  web前端  >  詳解javascript物件的資料屬性與存取器屬性

詳解javascript物件的資料屬性與存取器屬性

青灯夜游
青灯夜游轉載
2020-07-09 15:00:042441瀏覽

詳解javascript物件的資料屬性與存取器屬性

建立物件的方式有兩種:第一種,透過new運算子後面跟著Object建構函數,第二種,物件字面量方式。如下

var person = new Object();
person.name = 'Nicy';
person.age = 21;
person.sayName = function() {
    console.log(this.name);
};        
var person = {
    name: 'Nicy',
    age: 21,
    sayName: function() {
        console.log(this.name);
    }
}

這兩種方式建立出來的物件是一樣的,有相同的屬性和方法。這些屬性內部都有描述其行為的屬性描述符。

Object.defineProperty() 

#透過Object.defineProperty() 可以直接在物件上建立一個屬性,也可以修改現有的屬性。

Object.defineProperty(obj, prop, descriptor) 接收三個參數:

  obj:屬性所在的物件

  prop:要存取的屬性名稱

  descriptor:描述子物件

描述子物件包含六個屬性:configurable、enumerable、writable、value、get、set ,要修改屬性的特性,必須使用Object.defineProperty()方法。

透過上述兩種方式新增的物件屬性,其布林值特性預設值是true,透過Object.defineProperty來修改屬性特性時,只設定需要修改的特性即可;而透過Object .defineProperty所建立的屬性,其布林值特性預設值是false。

ECMAScript中屬性分為兩種:資料屬性和存取器屬性。

資料屬性

資料屬性包含四個屬性描述符:

#[[Configurable]] : 表示能否透過delete刪除屬性從而重新定義屬性,能否修改屬性特性,能否把屬性修改為存取器屬性。透過以上方式新增的物件屬性,預設為true。

[[Enumerable]] : 表示能否透過for-in 迴圈存取屬性。透過以上方式新增的物件屬性,預設為true。

[[Writable]] : 表示能否修改屬性的值。透過以上方式新增的物件屬性,預設為true。

[[Value]] : 包含這個屬性的資料值,可讀取寫入。透過以上方式新增的物件屬性,預設為undefined。

Writable

var person = {};

Object.defineProperty(person, "name", {
    value: 'Nicy'
})
person.name = 'Lee';  
console.log(person.name)    // 'Nicy'

Object.defineProperty(person, "name", {
    writable: true
})
person.name = 'Lee';
console.log(person.name)    // 'Lee'

Object.defineProperty直接建立的屬性writable預設為false,value值不可修改,此時修改name為Lee,在非嚴格模式下不會報錯,但操作被忽略,嚴格模式會報錯。

Configurable

<span style="font-size: 13px;"><span style="color: #0000ff;"></span>var person = {<br>    name: 'Nicy',<br>    age: 21,<br>    sayName: function() {<br>        console.log(this.name);<br>    }<br>}<br><br>Object.defineProperty(person, "name", {<br>    configurable: false<br>})<br><br>delete person.name;    // 操作被忽略,无法通过delete删除属性<br>Object.defineProperty(person, "name", {    // throw error<br>    configurable:true    <br>})     <br>Object.defineProperty(person, "name", {    // throw error<br>    enumerable: false<br>})  <br>Object.defineProperty(person, "name", {     // 由于writable为true,所以可以修改value<br>    value: 'Lucy'<br>})console.log(person.name)    // Lucy<br>Object.defineProperty(person, "name", {    // writable可进行true -> false的单向修改<br>    writable: false<br>})<br>Object.defineProperty(person, "name", {     // throw error<br>    value: 'Lee'<br>})<br>Object.defineProperty(person, "name", {    // throw error,此时writable不可以false -> true<br>    writable: true<br>})<span style="color: #000000;"></span></span>

總結configurable:當configurable設為false時,

  1、不可以透過delete去刪除該屬性從而重新定義屬性;

  2、不可以轉換為存取器屬性;

  3、configurable和enumerable無法修改;

  4、writable可單向修改為false,但不可以由false改為true;

  5、value是否可修改根據writable而定。

當configurable為false時,用delete刪除該屬性,在非嚴格模式下,不會報錯,但操作被忽略,在嚴格模式下會報錯;其他不可被修改的特性修改時會報錯。

Enumerable

enumerable表示物件屬性是否可以在for...in和Object.keys()中被列舉。

var person = {};
Object.defineProperty(person, "a", { value : 1, enumerable:true });
Object.defineProperty(person, "b", { value : 2, enumerable:false });
Object.defineProperty(person, "c", { value : 3 }); // enumerable defaults to false
person.d = 4; // 如果使用直接赋值的方式创建对象的属性,则这个属性的enumerable默认为true

for (var i in person) {    
  console.log(i);  
}  //  'a' 和 'd' 

Object.keys(person); // ["a", "d"]

存取器屬性

存取器屬性包含四個屬性描述符:

[[Configurable]] :表示能否透過delete刪除屬性從而重新定義屬性,能否修改屬性特性,能否把屬性修改為資料屬性。直接在物件上定義的屬性,預設為true。

[[Enumerable]] : 表示能否透過for-in 迴圈存取屬性。直接在物件上定義的屬性,預設為true。

[[Get]] : 讀取屬性時呼叫的函數,預設為undefined。

[[Set]] : 寫入屬性時呼叫的函數,預設為undefined。

var person = {
    name: 'Nicy',
    _age: 21,
    year: 1997,
    _year: 1997,
    sayName: function() {
        console.log(this.name);
    }
}

Object.defineProperty(person, "age", {
    get: function() {
        return this._age;
    },
    set: function(value) {
        this._age = value;
                // ...
    }
})

以Object.defineProperty()定義的存取器屬性,其configurable和enumerable預設為false。

資料屬性與存取器屬性的相互轉換

#Object.getOwnPropertyDescriptor 讀取屬性的特性

使用Object.getOwnPropertyDescriptor可以取得到屬性的描述子:

Object.getOwnPropertyDescriptor(obj, prop)

  obj:屬性所在的物件;

  obj:屬性所在的物件;  prop:要存取的屬性名稱。

資料屬性-> 存取器屬性

屬性的特性只能是存取器描述符和資料描述符中的一種,給已有的數據當屬性加get或set轉換為存取器屬性時,其屬性的value、writable就會被廢棄。 如下程式碼,將物件原有的資料屬性year轉換為存取器屬性:

*註:在存取器屬性的get和set中,不可以使用this訪問屬性本身,否則會無限遞歸而導致記憶體洩漏。

// 设置get和set其中任意一个即可转换为访问器属性
Object.defineProperty(person, "year", {
    get: function() {
//        return this,year;    // error
        return this._year;    
    },
    set: function(value) {
//             this.year = value;  // error
        this._year= value;
    }
})

var descriptor = Object.getOwnPropertyDescriptor(person, 'year');
console.log(descriptor);    // {get: ƒ, set: ƒ, enumerable: true, configurable: true}
在原有的資料屬性year中,使用Object.defineProperty()為屬性設定get 或 set,都可以轉換為存取器屬性。

######存取器屬性 -> 資料屬性#######

将访问器属性转换为数据属性,只需要给现有访问器属性设置value或writable这两个属性描述符中的任意一个即可,其原有的get和set就会被废弃,从而转换为数据属性。

上面为person定义的访问器属性age,通过Object.defineProperty()只设置了get和set,所以configurable默认为false,不可以将其转换为数据属性。可以在访问器属性和数据属性间相互转化的属性其configurable特性值必须为true。

如下代码,我们为person新定义一个访问器属性job,将其configurable设置为true ,并将其转换为数据属性:

Object.defineProperty(person, "job", {
    configurable: true,
    enumerable: true,
    get: function() {
        return this._job;
    },
    set: function(value) {
        this._job = value;
    }
})

// 设置value和writable其中任意一个即可转换为数据属性        
Object.defineProperty(person, "job", {
    value: 'worker',
    writable: true
})

var descriptor = Object.getOwnPropertyDescriptor(person, 'job');
console.log(descriptor);    // {value: "worker", writable: true, enumerable: true, configurable: true}

数据描述符value、writable 和访问器描述符get、set不能同时设置,否则会报错。

Object.defineProperties()

通过Object.defineProperties()可以一次性为对象定义多个属性。

var person = {};
Object.defineProperties(person, {
  name: {
    value: 'Nicy',
    writable: true
  },
  _age: {
    value: 21,
    enumerable: true,
    writable: true,
    configurable: true
  },
   age: {
    get: function() {
    return this._age;
    },
    set: function(value) {
    this._age = value;
    }
  }
});

 相关教程推荐:JavaScript视频教程

以上是詳解javascript物件的資料屬性與存取器屬性的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:cnblogs.com。如有侵權,請聯絡admin@php.cn刪除