快速理解Object.defineProperty( )

關於Object.defineProperty()

MDN解釋:Object.defineProperty()方法會直接在一個對象上定義一個新屬性,或者修改一個對象的現有屬性, 並返回這個對象。html

本文簡單的講解了 Object.defineProperty 有助於你快速瞭解 Object.defineProperty 想要詳細學習請移至MDN文檔數組

個人理解就是 當你操做一個對象(修改或者刪除屬性)時,Object.defineProperty能夠控制是否能夠去操做這個對象(修改、刪除屬性)或者修改、獲取屬性值時攔截你的操做而後do something。bash

語法 Object.defineProperty(obj, prop, descriptor)

obj 要操做的對象
prop 要定義或修改的屬性的名稱
descriptor 將被定義或修改的屬性描述符
複製代碼

先看一下基本使用,而後下面會具體講解一下屬性描述符。ide

var obj = {};
Object.defineProperty(obj,'name',{
    value:'chenm'
});
console.log(obj.name); //chenm
複製代碼

descriptor屬性描述符

分爲數據描述符和存取描述符
學習

configurable:爲 true 時,該屬性描述符纔可以再次被改變,同時該屬性也能從對應的對象上被刪除。默認爲 false。

enumerable:爲true時,該屬性纔可以出如今對象的枚舉屬性中。默認爲 false。

value:該屬性的值,默認爲 undefined。

writable:爲true時,屬性的值才能被 ‘=’ 賦值。默認爲 false。

get:一個給屬性提供 getter 的方法,若是沒有 getter 則爲 undefined。當訪問(獲取)該屬性時,該方法會被執行,方法執行時沒有參數傳入,
可是會傳入this對象(因爲繼承關係,這裏的this並不必定是定義該屬性的對象)。

set:一個給屬性提供 setter 的方法,若是沒有 setter 則爲 undefined。當修改屬性值時,觸發執行該方法。該方法將接受惟一參數,即該屬性新的參數值。
複製代碼
configurable:爲 true 時,該屬性描述符纔可以再次被改變,同時該屬性也能從對應的對象上被刪除。默認爲 false。
//1.configurable爲false
var obj = {age:25};
Object.defineProperty(obj,'name',{
    configurable:false,
    value:'chenm'
});
delete obj.name; 
console.log(obj.name); //chenm
//configurable 爲false時(固然默認就爲false),name不容許被刪除,因此打印obj.name 仍是chenm

//注意當操做對象現有屬性的時候 configurable默認爲true

//2.configurable爲 true
Object.defineProperty(obj,'age',{
    value:'26'
});
delete obj.age; 
console.log(obj.age); //undefined
複製代碼
enumerable:爲true時,該屬性纔可以出如今對象的枚舉屬性中。默認爲 false。
//1.enumerable爲false
var obj = {age:25};
Object.defineProperty(obj,'name',{
    enumerable:false,
    value:'chenm'
});
for(let key in obj){
    console.log(key)     //age
}
console.log(Object.keys(obj))//["age"]
//Object.keys:返回該對象可枚舉屬性組成的數組。 enumerable爲false時,name並不能枚舉。

//注意當操做對象現有屬性的時候 enumerable默認爲true

//2.enumerable爲true
var obj = {age:25};
Object.defineProperty(obj,'name',{
    enumerable:true,
    value:'chenm'
});
for(let key in obj){
    console.log(key) //age name
}
console.log(Object.keys(obj)) //["age","name"]
複製代碼
value:該屬性的值,默認爲 undefined。
var obj = {};
Object.defineProperty(obj,'name',{
    value:'chenm'
});
console.log(obj.name); //chenm
Object.defineProperty(obj,'sex',{
    
});
console.log(obj.sex); //undefined
//不設置value時 改屬性的值爲 undefined
複製代碼
writable:爲true時,屬性的值才能被 ‘=’ 賦值。默認爲 false。
//1.writable爲false
var obj = {};
Object.defineProperty(obj,'sex',{
    writable:false,
    value:'boy'
});
console.log(obj.sex); //boy
obj.sex = 'girl';
console.log(obj.sex); //boy
//writable 爲false(默認就爲false),sex是不能用'='賦值的。

//2.writable爲true
var obj = {};
Object.defineProperty(obj,'sex',{
    writable:true,
    value:'boy'
});
console.log(obj.sex)  //boy
obj.sex = 'girl'
console.log(obj.sex)  //girl
複製代碼
get:一個給屬性提供 getter 的方法。當訪問(獲取)該屬性時,該方法會被執行。
set:一個給屬性提供 setter 的方法。當修改該屬性值時,該方法會被執行。
var obj = {};
let val = '15k';
Object.defineProperty(obj,'wages',{
    get:function(){
    	//這是裏獲取屬性的時候執行
    	console.log('我獲取到你的值了。。。')
    	return val;
    },
    set:function(newVal){
        //這是裏修改屬性值的時候執行
        console.log('我修改了你的值。。。')
    	val = newVal
    }
});
console.log(obj.wages);
obj.wages = '20k'
console.log(obj.wages);
//我獲取到你的值了。。。
//15k
//我修改了你的值。。。
//我獲取到你的值了。。。
//20k
複製代碼
//get,set一塊兒出現,若是省略get,獲取到的值都是undefined
var obj = {};
let val = '15k';
Object.defineProperty(obj,'wages',{
    set:function(newVal){
        //這是裏修改屬性值的時候執行
        console.log('我修改了你的值。。。')
        val = newVal
    }
});
console.log(obj.wages) //undefined
obj.wages = '20k' 
console.log(obj.wages)//undefined

//若是省略set, 沒法賦值。
var obj = {};
let val = '15k';
Object.defineProperty(obj,'wages',{
    get:function(){
    	//這是裏獲取屬性的時候執行
    	console.log('我獲取到你的值了。。。')
    	return val;
    },
});
console.log(obj.wages) //15k
obj.wages = '20k' 
console.log(obj.wages)//15k
複製代碼

注意:ui

//get,set與writable,value不能共用
var obj = {};
let val = '15k';
Object.defineProperty(obj,'wages',{
    value:'20k'
    set:function(newVal){
        //這是裏修改屬性值的時候執行
        console.log('我修改了你的值。。。')
    	val = newVal
    }
});
//Uncaught SyntaxError: Unexpected identifier
複製代碼

tips:操做對象的現有屬性和用Object.defineProperty()添加的屬性,描述符的默認值是有所的同的。this

現有屬性描述符默認值:
configurable:true
enumerable:true
writable:true

Object.defineProperty()添加的屬性描述符默認值:
configurable:false
enumerable:false
writable:false
複製代碼

根據Object.defineProperty()的get,set寫一個簡單的數據雙向綁定。

<!DOCTYPE html>
<html>
    <head>
    	<meta charset="UTF-8">
    	<title></title>
    </head>
    <body>
    <input type="text" id="input"/>
    <span id="text"></span>
    <button id="btn1">獲取值</button>
    <button id="btn2">修改值</button>
    <script>
        var obj = {
            value:123
        };
        //初始化賦值
        document.getElementById('input').value = obj.value;
        document.getElementById('text').innerHTML = obj.value;
        
        //監聽input方法
        document.getElementById('input').oninput = function(e){
    	    obj.value = e.target.value;
        };
        
        
        //使用Object.defineProperty設置屬性的get,set方法。
        let val = obj.value;
        Object.defineProperty(obj,'value',{
    	get:function(){
            return val
    	},
    	set:function (newVal){
            //當值被修改的時候 修改input&span的值
            document.getElementById('input').value = newVal;
            document.getElementById('text').innerHTML = newVal;
            val = newVal;
    	}
        });
        document.getElementById('btn1').onclick = function (){
    	    console.log(obj)
        }
        document.getElementById('btn2').onclick = function (){
    	    obj.value = '修改了';
        }
    </script>
    </body>
</html>
複製代碼

路過點個贊呦~~spa

相關文章
相關標籤/搜索