Object.defineProperty

[TOC]html

Object.defineProperty

Object.defineProperty ,顧名思義,爲對象定義屬性。在js中咱們能夠經過下面這幾種方法定義屬性.git

// (1) define someOne property name
someOne.name = 'cover';
//or use (2) 
someOne['name'] = 'cover';
// or use (3) defineProperty
Object.defineProperty(someOne, 'name', {
    value : 'cover'
})

從上面看,貌似使用Object.defineProperty很麻煩,那爲啥存在這樣的方法呢?github

帶着疑問,咱們來看下 Object.defineProperty的定義。web

基礎知識

Object.defineProperty(object, propertyname, descriptor)dom

  • object 必需。 要在其上添加或修改屬性的對象。 這多是一個本機 JavaScript對象(即用戶定義的對象或內置對象)或 DOM 對象。
  • propertyname 必需。 一個包含屬性名稱的字符串。
  • descriptor 必需。 屬性描述符。 它能夠針對數據屬性或訪問器屬性。

其中descriptor的參數值得咱們關注下,該屬性可設置的值有:mvvm

  • 【value】 屬性的值,默認爲 undefined。
  • 【writable】 該屬性是否可寫,若是設置成 false,則任何對該屬性改寫的操做都無效(但不會報錯),對於像前面例子中直接在對象上定義的屬性,這個屬性該特性默認值爲爲 true。
var someOne = { };
Object.defineProperty(someOne, "name", {
    value:"coverguo" , //因爲設定了writable屬性爲false 致使這個量不能夠修改
    writable: false 
});  
console.log(someOne.name); // 輸出 coverguo
someOne.name = "linkzhu";
console.log(someOne.name); // 輸出coverguo
  • [configurable] 若是爲false,則任未嘗試刪除目標屬性或修改屬性如下特性(writable, configurable, enumerable)的行爲將被無效化,對於像前面例子中直接在對象上定義的屬性,這個屬性該特性默認值爲爲 true。
var someOne = { };
Object.defineProperty(someOne, "name", {
    value:"coverguo" ,
    configurable: false 
});  
delete someOne.name; 
console.log(someOne.name);// 輸出 coverguo
someOne.name = "linkzhu";
console.log(someOne.name); // 輸出coverguo
  • 【enumerable】 是否能在for-in循環中遍歷出來或在Object.keys中列舉出來。對於像前面例子中直接在對象上定義的屬性,這個屬性該特性默認值爲爲 true。

注意 在調用Object.defineProperty()方法時,若是不指定, configurable, enumerable, writable特性的默認值都是false,這跟以前所 說的對於像前面例子中直接在對象上定義的屬性,這個特性默認值爲爲 true。並不衝突,以下代碼所示:優化

//調用Object.defineProperty()方法時,若是不指定
var someOne = { };
someOne.name = 'coverguo';
console.log(Object.getOwnPropertyDescriptor(someOne, 'name'));
//輸出 Object {value: "coverguo", writable: true, enumerable: true, configurable: true}

//直接在對象上定義的屬性,這個特性默認值爲爲 true
var otherOne = {};
Object.defineProperty(otherOne, "name", {
    value:"coverguo" 
});  
console.log(Object.getOwnPropertyDescriptor(otherOne, 'name'));
//輸出 Object {value: "coverguo", writable: false, enumerable: false, configurable: false}
  • 【get】一旦目標對象訪問該屬性,就會調用這個方法,並返回結果。默認爲 undefined。
  • 【set】 一旦目標對象設置該屬性,就會調用這個方法。默認爲 undefined。

從上面,能夠得知,咱們能夠經過使用Object.defineProperty,來定義和控制一些特殊的屬性,如屬性是否可讀,屬性是否可枚舉,甚至修改屬性的修改器(setter)和獲取器(getter).動畫

優化對象獲取和修改屬性方式

//加入有一個目標節點, 咱們想設置其位移時是這樣的
var targetDom = document.getElementById('target');
var transformText = 'translateX(' + 10 + 'px)';
targetDom.style.webkitTransform = transformText;
targetDom.style.transform = transformText;

經過上面,能夠看到若是頁面是須要許多動畫時,咱們這樣編寫transform屬性是十分蛋疼的。(┬_┬)this

但若是經過Object.defineProperty, 咱們則能夠spa

//這裏只是簡單設置下translateX的屬性,其餘如scale等屬性可本身去嘗試

Object.defineProperty(dom, 'translateX', {
set: function(value) {
         var transformText = 'translateX(' + value + 'px)';
        dom.style.webkitTransform = transformText;
        dom.style.transform = transformText;
}
//這樣再後面調用的時候, 十分簡單
dom.translateX = 10;
dom.translateX = -10;
//甚至能夠拓展設置如scale, originX, translateZ,等各個屬性,達到下面的效果
dom.scale = 1.5;  //放大1.5倍
dom.originX = 5;  //設置中心點X
}

簡單實現視圖和數據變化綁定

<div>
    <p>你好,<span id='nickName'></span></p>
    <div id="introduce"></div>
  <input type="text" id='inputDom'/>
</div> 
//視圖控制器
var userInfo = {};
Object.defineProperty(userInfo, "nickName", {
    get: function(){
        return document.getElementById('nickName').innerHTML;
    },
    set: function(nick){
        document.getElementById('nickName').innerHTML = nick;
    }
});
Object.defineProperty(userInfo, "introduce", {
    get: function(){
        return document.getElementById('introduce').innerHTML;
    },
    set: function(introduce){
        document.getElementById('introduce').innerHTML = introduce;
    }
})

而後就能愉快地綁定數據交互了.

userInfo.nickName = "xxx";
userInfo.introduce = "我是xxx,..."
$('#inputDom').on('keyup',funtion(){
      userInfo.nickName = this.value();
});

參考

https://juejin.im/entry/59116...
https://juejin.im/entry/59239...
https://github.com/DMQ/mvvm

相關文章
相關標籤/搜索