Object.defineProperty()

簡介

源碼地址
01javascript

Object.defineProperty(對象,屬性,屬性描述符) 用於在一個對象上定義一個新的屬性,或者修改一個對象現有的屬性,並返回這個對象。html

demo01 - 屬性描述符默認值

屬性 默認值 說明
configurable false 描述屬性是否能夠被刪除,默認爲 false
enumerable false 描述屬性是否能夠被for...in或Object.keys枚舉,默認爲 false
writable false 描述屬性是否能夠修改,默認爲 false
get undefined 當訪問屬性時觸發該方法,默認爲undefined
set undefined 當屬性被修改時觸發該方法,默認爲undefined
value undefined 屬性值,默認爲undefined
// demo01-default.html

// Object.defineProperty(對象,屬性,屬性描述符)
  var obj = {};
  console.log('obj:', obj);
  // 默認不可刪除,不可枚舉,不可修改
  Object.defineProperty(obj, 'name', {
    value: 'Jameswain'
  });
  console.log('obj默認值:', obj);
  delete obj.name;
  console.log('obj刪除後:', obj);
  console.log('obj枚舉:', Object.keys(obj));
  obj.name = '詹姆斯,韋恩';
  console.log('obj修改後:', obj);
  // 不能從新定義,會報重複定義錯誤: Uncaught TypeError: Cannot redefine property: name
  Object.defineProperty(obj, 'name', {
    value: '詹姆斯,韋恩'
  });

運行結果:java

02

​ 從運行結果能夠發現,使用Object.defineProperty()定義的屬性,默認是不能夠被修改,不能夠被枚舉,不能夠被刪除的。能夠與常規的方式定義屬性對比一下:若是不使用Object.defineProperty()定義的屬性,默認是能夠修改、枚舉、刪除的:node

const obj = {};
 obj.name = 'Jameswain';
 console.log('枚舉:', Object.keys(obj));
 obj.name = '詹姆斯-韋恩';
 console.log('修改:', obj);
 delete obj.name;
 console.log('刪除:', obj);

03

demo02 - 屬性描述符

// JavaScript/Object.defineProperty/demo02-descriptor.html
  const o = {};
  Object.defineProperty(o, 'name', {
    value: 'Jameswain',   // name屬性值
    writable: true,       // 能夠被修改
    enumerable: true,     // 能夠被枚舉
    configurable: true,   // 能夠被刪除
  });
  console.log(o);
  console.log('枚舉:', Object.keys(o));
  o.name = '詹姆斯-韋恩';
  console.log('修改:', o);
  Object.defineProperty(o, 'name', {
    value: 'Po'
  });
  console.log('修改:', o);
  delete o.name;
  console.log('刪除:', o);

運行結果:git

04

⚠️注意:若是writable爲false,configurable爲true時,經過o.name = "詹姆斯-韋恩"是沒法修改爲功的,可是使用Object.defineProperty()修改是能夠成功的代碼以下:github

const o = {};
  Object.defineProperty(o, 'name', {
    value: 'Jameswain',   // name屬性值
    writable: false       // 不可被修改
    enumerable: true,     // 能夠被枚舉
    configurable: true,   // 能夠被刪除
  });
  console.log(o);
  console.log('枚舉:', Object.keys(o));
  o.name = '詹姆斯-韋恩';
  console.log('修改:', o);
  Object.defineProperty(o, 'name', {
    value: 'Po'
  });
  console.log('修改:', o);
  delete o.name;
  console.log('刪除:', o);

05

⚠️注意:若是writable和configurable都爲false時,若是使用Object.defineProperty()修改屬性值會報錯:Cannot redefine property: name數組

const o = {};
  Object.defineProperty(o, 'name', {
    value: 'Jameswain',   // name屬性值
    writable: false,       // 不可被修改
    enumerable: true,     // 能夠被枚舉
    configurable: false,   // 不可被刪除
  });
  console.log(o);
  console.log('枚舉:', Object.keys(o));
  o.name = '詹姆斯-韋恩';
  console.log('修改:', o);
  Object.defineProperty(o, 'name', {
    value: 'Po'
  });
  console.log('修改:', o);
  delete o.name;
  console.log('刪除:', o);

06

demo03 - enumerable

// JavaScript/Object.defineProperty/demo03-enumerable.html
const o = {};
Object.defineProperty(o, 'name', { value: 'Jameswain', enumerable: true });
Object.defineProperty(o, 'trim', { value: (str) => { return str.trim() }, enumerable: false });
Object.defineProperty(o, 'email', { value: 'Jameswain@163.com' });
o.skill = 'node.js';
console.log('枚舉:', Object.keys(o));
console.log('trim: ', o.trim('      8888       ') + '1')
console.log(`o.propertyIsEnumerable('name'): `, o.propertyIsEnumerable('name'));
console.log(`o.propertyIsEnumerable('trim'): `, o.propertyIsEnumerable('trim'));
console.log(`o.propertyIsEnumerable('email'): `, o.propertyIsEnumerable('email'));

07

demo04 - set 和 get

⚠️注意:設置set或者get,就不能在設置value和wriable,不然會報錯函數

const o = {
    __name: ''
  };
  Object.defineProperty(o, 'name', {
    enumerable: true,
    configurable: true,
    // writable: true,    // 若是設置了get或者set,writable和value屬性必須註釋掉
    // value: '',         // writable和value沒法與set和get共存
    get: function () {    // 若是設置了get 或者 set 就不能設置writable和value
      console.log('get', this);
      return 'My name is ' + this.__name;
    },
    set: function (newVal) {
      localStorage.setItem('name', newVal);
      console.log('set', newVal);
      this.__name = newVal;
    }
  });
  console.log(o);
  o.name = 'Jameswain';
  o.name;
  console.log(o);
  o.name = '詹姆斯-韋恩';
  console.log(o);

08

demo05 - set 和 get 數據驅動視圖

​ 咱們能夠利用set和get實現數據驅動視圖變化功能,主要經過監聽屬性,屬性變化時更新視圖,獲取數據從視圖中獲取:this

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>set & get 數據驅動視圖</title>
</head>
<body>
  <div id="name"></div>
  <div id="skills"></div>
  <script type="text/javascript">
    const profile = {};
    Object.defineProperty(profile, 'name', {
      enumerable: true,
      configurable: true,
      get: function () {
        return document.querySelector('#name').innerHTML;
      },
      set: function (newVal) {
        document.querySelector('#name').innerHTML = newVal;
      }
    });
    Object.defineProperty(profile, 'skills', {
      get: () => document.querySelector('#skills').innerHTML.split(','),
      set: newVal => document.querySelector('#skills').innerHTML = newVal.toString()
    });
  </script>
</body>
</html>

運行結果:spa

09

​ 從運行結果中,咱們能夠發現profile.skills屬性是一個數組,若是直接更新整個數組內容是能夠驅動視圖變化的,可是若是更新數組對象中的某個元素是不會觸發set函數的。

相關文章
相關標籤/搜索