Object.defineProperty()詳解


        在園子里看到一篇講解Object.defineProperty()的非常好的博文,我把他轉載過來,給自己留個筆記。原文出處https://www.cnblogs.com/junjun-001/p/11761252.html#commentform

  菜菜: “老大,那個, Object.defineProperty 是什么鬼?”

  假設我們有個對象 user ; 我們要給它增加一個屬性 name , 我們會這么做  

1 var user = {};
2 user.name="狂奔的蝸牛";
3 console.log(user);//{name: "狂奔的蝸牛"}

  如果想要增加一個sayHi方法叻?  

1 user.sayHi=function () { console.log("Hi !") };
2 console.log(user);//{name: "狂奔的蝸牛", sayHi: ƒn}

  Object.defineProperty 就是做這個的

  那么Object.defineProperty 怎么用?

  Object.defineProperty 需要三個參數(object , propName , descriptor)

  1 object 對象 => 給誰加
  2 propName 屬性名 => 要加的屬性的名字 【類型:String】
  3 descriptor 屬性描述 => 加的這個屬性有什么樣的特性【類型:Object】

  那么descriptor這個是個對象 ,他有那些屬性呢 ? 別着急我們一個一個說;

  既然可以給一個對象增加屬性,那么我們用它來做一下給 user添加 name屬性,代碼是這樣的  

1 var user = {};
2 Object.defineProperty(user,"name",{
3  value:"狂奔的蝸牛"
4 })
5 console.log(user);//{name: "狂奔的蝸牛"}

  說明 是的還是那個經典的value屬性,他就是設置屬性值的。

  等等,屬性值只能為字符串嗎?我們的 number function Object boolean 等呢?  

 1 var user = {};
 2 Object.defineProperty(user,"name",{
 3  value:"狂奔的蝸牛"
 4 })
 5 Object.defineProperty(user,"isSlow",{
 6  value:true
 7 })
 8 Object.defineProperty(user,"sayHi",{
 9  value:function () { console.log("Hi !") }
10 })
11 Object.defineProperty(user,"age",{
12  value:12
13 })
14 Object.defineProperty(user,"birth",{
15  value:{
16   date:"2018-06-29",
17   hour:"15:30"
18  }
19 })
20 console.log(user);

   

   說明 事實證明任何類型的數據都是可以的哦~

  問題又來了,如果 user對象已經有了name屬性,我們可以通過Object.defineProperty改變這個值嗎?

  我們來試試

1 var user = {};
2 Object.defineProperty(user,"name",{
3  value:"狂奔的蝸牛"
4 })
5 console.log(user);
6 user.name="新=>狂奔的蝸牛"
7 console.log(user);

  咦??為什么我改了沒作用勒??

  原因:上邊說了descriptor有很多屬性,除了value屬性還有個 writable【顧名思義屬性是否可以被重新賦值】接受數據類型為 boolean(默認為false) true => 支持被重新賦值 false=>只讀

  哦哦,原來如果我沒設置writable值的時候就默認只讀啊,所以才改不掉

  那我們看看,設置為true,是不是就可以改掉了。

1 var user = {};
2 Object.defineProperty(user,"name",{
3  value:"狂奔的蝸牛",
4  writable:true
5 })
6 console.log(user);
7 user.name="新=>狂奔的蝸牛"
8 console.log(user);

 

  這個descriptor還有其他的屬性嗎?enumerable【顧名思義屬性是否可以被枚舉】接受數據類型為 boolean(默認為false) true => 支持被枚舉 false=>不支持

 

  額。。。枚舉??什....什么意思?

  假設我們想知道這個 user對象有哪些屬性我們一般會這么做   

 1 var user ={
 2  name:"狂奔的蝸牛",
 3  age:25
 4 } ;
 5  
 6 //es6
 7 var keys=Object.keys(user)
 8 console.log(keys);// ['name','age']
 9 //es5
10 var keys=[];
11 for(key in user){
12  keys.push(key);
13 } 
14 console.log(keys);// ['name','age'] 

  如果我們使用 Object.的方式定義屬性會發生什么呢?我們來看下輸出

 1 var user ={
 2  name:"狂奔的蝸牛",
 3  age:25
 4 } ;
 5 //定義一個性別 可以被枚舉
 6 Object.defineProperty(user,"gender",{
 7  value:"男",
 8  enumerable:true
 9 })
10  
11 //定義一個出生日期 不可以被枚舉
12 Object.defineProperty(user,"birth",{
13  value:"1956-05-03",
14  enumerable:false
15 })
16  
17 //es6
18 var keys=Object.keys(user)
19 console.log(keys);
20 // ["name", "age", "gender"]
21  
22 console.log(user);
23 // {name: "狂奔的蝸牛", age: 25, gender: "男", birth: "1956-05-03"}
24 console.log(user.birth);
25 // 1956-05-03 

  說明 很明顯,我們定義為 enumerable=falsebirth屬性並沒有被遍歷出來,遍歷 => 其實就是枚舉(個人理解啦,不喜勿噴哦~)

  總結 enumerable 屬性取值為 布爾類型 true | false 默認值為 false,為真屬性可以被枚舉;反之則不能。此設置不影響屬性的調用和 查看對象的值。

  configurable 是接下來我們要講的一個屬性,這個屬性有兩個作用:

  1 屬性是否可以被刪除
  2 屬性的特性在第一次設置之后可否被重新定義特性

 1 var user ={
 2  name:"狂奔的蝸牛",
 3  age:25
 4 } ;
 5 //定義一個性別 不可以被刪除和重新定義特性
 6 Object.defineProperty(user,"gender",{
 7  value:"男",
 8  enumerable:true,
 9  configurable:false
10 })
11  
12 //刪除一下
13 delete user.gender;
14 console.log(user);//{name: "狂奔的蝸牛", age: 25, gender: "男"}
15  
16 //重新定義特性
17 Object.defineProperty(user,"gender",{
18  value:"男",
19  enumerable:true,
20  configurable:true
21 })
22 // Uncaught TypeError: Cannot redefine property: gender
23 //會報錯,如下圖

  

 

 

   設置為 true

 1 var user ={
 2  name:"狂奔的蝸牛",
 3  age:25
 4 } ;
 5 //定義一個性別 可以被刪除和重新定義特性
 6 Object.defineProperty(user,"gender",{
 7  value:"男",
 8  enumerable:true,
 9  configurable:true
10 })
11  
12 //刪除前
13 console.log(user);
14 // {name: "狂奔的蝸牛", age: 25, gender: "男"}
15  
16 //刪除一下
17 delete user.gender;
18 console.log(user);
19 // {name: "狂奔的蝸牛", age: 25}
20  
21 //重新定義特性
22 Object.defineProperty(user,"gender",{
23  value:"男",
24  enumerable:true,
25  configurable:false
26 })
27  
28 //刪除前
29 console.log(user);
30 // {name: "狂奔的蝸牛", age: 25, gender: "男"}
31 //刪除一下 刪除失敗
32 delete user.gender;
33 console.log(user);
34 // {name: "狂奔的蝸牛", age: 25, gender: "男"}

  總結 configurable設置為 true 則該屬性可以被刪除和重新定義特性;反之屬性是不可以被刪除和重新定義特性的,默認值為false(Ps.除了可以給新定義的屬性設置特性,也可以給已有的屬性設置特性哈

  最后我們來說說,最重要的兩個屬性 setget(即存取器描述:定義屬性如何被存取),這兩個屬性是做什么用的呢?我們通過代碼來看看

 1 var user ={
 2  name:"狂奔的蝸牛"
 3 } ;
 4 var count = 12;
 5 //定義一個age 獲取值時返回定義好的變量count
 6 Object.defineProperty(user,"age",{
 7  get:function(){
 8   return count;
 9  }
10 })
11 console.log(user.age);//12
12  
13 //如果我每次獲取的時候返回count+1呢
14 var user ={
15  name:"狂奔的蝸牛"
16 } ;
17 var count = 12;
18 //定義一個age 獲取值時返回定義好的變量count
19 Object.defineProperty(user,"age",{
20  get:function(){
21   return count+1;
22  }
23 })
24 console.log(user.age);//13

  接下來我不用解釋了吧,你想在獲取該屬性的時候對值做什么隨你咯~

  來來來,我們看看 set,不多說上代碼

 1 var user ={
 2  name:"狂奔的蝸牛"
 3 } ;
 4 var count = 12;
 5 //定義一個age 獲取值時返回定義好的變量count
 6 Object.defineProperty(user,"age",{
 7  get:function(){
 8   return count;
 9  },
10  set:function(newVal){
11   count=newVal;
12  }
13 })
14 console.log(user.age);//12
15 user.age=145;
16 console.log(user.age);//145
17 console.log(count);//145
18  
19 //等等,如果我想設置的時候是 自動加1呢?我設置145 實際上設置是146
20  
21 var user ={
22  name:"狂奔的蝸牛"
23 } ;
24 var count = 12;
25 //定義一個age 獲取值時返回定義好的變量count
26 Object.defineProperty(user,"age",{
27  get:function(){
28   return count;
29  },
30  set:function(newVal){
31   count=newVal+1;
32  }
33 })
34 console.log(user.age);//12
35 user.age=145;
36 console.log(user.age);//146
37 console.log(count);//146

  說明 注意:當使用了getter或setter方法,不允許使用writable和value這兩個屬性(如果使用,會直接報錯滴)

  get 是獲取值的時候的方法,類型為 function ,獲取值的時候會被調用,不設置時為 undefined

  set 是設置值的時候的方法,類型為 function ,設置值的時候會被調用,undefined

  get或set不是必須成對出現,任寫其一就可以

 1 var user ={
 2  name:"狂奔的蝸牛"
 3 } ;
 4 var count = 12;
 5 //定義一個age 獲取值時返回定義好的變量count
 6 Object.defineProperty(user,"age",{
 7  get:function(){
 8   console.log("這個人來獲取值了!!");
 9   return count;
10  },
11  set:function(newVal){
12   console.log("這個人來設置值了!!");
13   count=newVal+1;
14  }
15 })
16 console.log(user.age);//12
17 user.age=145;
18 console.log(user.age);//146

  

 

   【完結】

  Object.defineProperty方法直接在一個對象上定義一個新屬性,或者修改一個已經存在的屬性, 並返回這個對象

  • value: 設置屬性的值
  • writable: 值是否可以重寫。true | false
  • enumerable: 目標屬性是否可以被枚舉。true | false
  • configurable: 目標屬性是否可以被刪除或是否可以再次修改特性 true | false
  • set: 目標屬性設置值的方法
  • get:目標屬性獲取值的方法 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM