1. 程式人生 > >javascript-object對象屬性操作之Object.defineProperty

javascript-object對象屬性操作之Object.defineProperty

終極 {} name屬性 ble -o 常量 沒有 tab 是否

一、基本用法簡介

聲明一個簡單的對象,如下

var obj = {
  name: ‘ldld‘
}

 我們可以用Object.defineProperty來聲明這個對象

var obj = {}
Object.defineProperty(obj,‘name‘,{
  value:‘ldld‘,
  writable:true,
  enumerable: true,
  configurable: true
})

下列就這四個基本的配置簡單介紹一下

  1. value:初始值
  2. writable:是否可以修改該屬性的值
    var obj = {}
    Object.defineProperty(obj,‘name‘,{
      value:‘ldld‘,
      writable:false,
      enumerable: true,
      configurable: true
    })
    
    obj.name // ‘ldld‘
    obj.name = ‘LLLL‘; // 這裏會修改失敗,嚴格模式下會報錯 TypeError
    console.log(obj.name) // ‘ldld‘
  3. enumerable:是否可枚舉,這個是否能遍歷到該屬性(for)
  4. configurable : 這個得重點講一下
    var obj = {}
    // 第一次設置操作configurable配置,設置為false
    Object.defineProperty(obj,‘name‘,{
      value:‘ldld‘,
      writable:true,
      enumerable: true,
      configurable: false
    })
    
    obj.name // ‘ldld‘
    obj.name = ‘LLLL‘; //  configurable: false 不影響writable屬性,這裏可以設置成功
    console.log(obj.name) // ‘LLLL‘
    
    // 第二次設置操作configurable配置,在第一步false基礎上改回true
    Object.defineProperty(obj,‘name‘,{
      value:‘ldld‘,
      writable:true,
      enumerable: true,
      configurable: true // 現在我們想改回來,但是很遺憾,不能。不管是嚴格模式還是非嚴格模式都會報錯
    })
    

     此外,configurable會影響該對象屬性是否可以被刪除

    Object.defineProperty(obj,‘name‘,{
      value:‘ldld‘,
      writable:true,
      enumerable: true,
      configurable: true
    })
    
    delete obj.name;
    console.log(obj.name) // undefined ,說明刪除成功
    
    
    Object.defineProperty(obj,‘name‘,{
      value:‘ldld‘,
      writable:true,
      enumerable: true,
      configurable: false
    })
    
    delete obj.name;
    console.log(obj.name) // ldld, 說明name屬性沒有被刪除


二、對象常量

const str = ‘abc‘;
str = ‘def‘; // 報錯Uncaught TypeError: Assignment to constant variable.

const obj = {name:‘ldld‘};
obj.name = {
  name:‘ldld1234‘ //  這裏會修改成功
}

  const聲明的對象不可變,實際上是可以理解為指針的不可變。

const str = ‘abc‘; 表示str指針指向棧中一個地址,值‘abc‘;

str = ‘def‘;表示str又指到另一個地址,值為‘def‘,違反了不可變的規則,報錯了。

const obj = {name:‘ldld‘};表示obj 對象指向一個堆 內存堆的obj的引用,不管怎麽改變obj裏面的值,在內存堆中地方始終不變,因此不會報錯。

那麽問題來了,我們想聲明一個不可變的對象,那怎麽辦?可以參考如下:

var obj = {}
Object.defineProperty(obj,‘name‘,{
  value:‘ldld‘,
  writable:false,
  configurable: false
})
// 此時問obj的name屬性不可改變了。

  但是問題來來,name是不能再改變,但是我們可以給對象擴展其他屬性。。。

三、防止對象擴展Object.preventExtensions

var obj = {}
Object.defineProperty(obj,‘name‘,{
  value:‘ldld‘,
  writable:false,
  configurable: false
})
// 此時問obj的name屬性不可改變了。但是可以擴展obj屬性
obj.age = 100;
console.log(obj.age) // 100 

Object.preventExtensions(obj);
obj.sex = ‘male‘;
console.log(obj.sex) // undefined,說明擴展失敗

  

四、密封Object.seal

顧名思義,密封一個對象,這個對象不能配置,不能擴展屬性,不能刪除屬性。但是可以可以修改熟悉過的值

Object.seal(obj)// 等同於如下:代碼1 + 代碼2
// 代碼1
Object.defineProperty(obj,‘[該對象所有的屬性]‘,{
  configurable: false
  // writable:true, // 此時默認為true,可以修改
})
// 代碼2
Object.preventExtensions(obj);

  

四、凍結Object.freeze(obj)

Object.freeze(obj)// 等同於如下:代碼1 + 代碼2
// 代碼1
Object.seal(obj)
// 代碼2 
Object.defineProperty(obj,‘[該對象所有的屬性]‘,{
  writable:false
})

  

由此可見,凍結,就是定一個對象常量的終極大法。




javascript-object對象屬性操作之Object.defineProperty