查看原文
其他

谈谈js属性的纠结往事

2016-10-21 jimmy_thr 前端圈

属性

前几天看了一下,es5的属性值,才发现里面的东西还挺深,挺坑的。原来写属性,无非就是像这样。


  1. var People={ 

  2.     name:"Jimmy"

  3.     age:18 

  4. //或者 

  5. var People = new Object(); 

  6. People.name = "Jimmy"

  7. People.age = 18;

一个是字面量定义,一个是创建实例添加属性. 后来看了js高级程序设计才知道,js中的属性我才用了50%. 为什么这么说呢?


因为js中的属性分为数据属性访问器属性(descriptor),而我们通常写的属性只是数据属性,而且还有一些细节比如 [[writable]],[[enumberable]],[[value]] 等一些相关的设置我们都还没有涉及。
来,我们细细谈一下。


1、数据属性

数据属性,就是我们平常定义的一些属性。

  1. var Property = { 

  2.     name:"property" 

  3. }


但是,一门高级的语言不会让你知道 你到底哪里不知道.
在es5中, 对属性进行了更细的定义, 一个数据属性有4个配置项:

  1. [[writable]] :(Boolean) 是否可以修改属性的值 

  2.  

  3. [[Enumerable]] :(Boolean)是否可以通过for...in 循环出来 

  4.  

  5. [[Configurable]] :(Boolean)是否可以通过delete关键字删除 

  6.  

  7. [[value]] :(xxx) 属性的内容,类型未知


如果想使用者4个配置项的话,需要使用到es5新定义的一个方法. Object.defineProperty();老板啊喂,来个栗子~

  1. var person = {}; 

  2.  

  3. Object.defineProperty(person,"name",{  person.name; 

  4. writable: false

  5. //不能修改属性的值 

  6. value: "Nicholas"

  7. //属性的值 

  8. configurable: false

  9. //不能通过delete删除该属性 

  10. Enumerable: false 

  11. //不能通过for...in 遍历出该属性 

  12. });

Object.defineProperty(para1,para2,para3)里面第一个参数就是你要修改属性的对象, 第二个就是你要修改的属性,第三个就是详细的配置项。


看完这些不是不觉得脑袋蒙蒙哒, 对的,因为我们平常用不到,而且以后也很少会用。但是对于理解js这门 OO(Object-Oriented) 为标杆的语言是非常有利的。 


平常我们使用字面量定义,比如:

  1. var people = { 

  2.     name:"Jimmy" 

  3. }

js默认认为你的3个配置项(不包括value); 都是默认为true的. 如果你使用Object.defineProperty()定义(那你真是吃饱了没事,来秀技的):


  1. var person = {}; 

  2. Object.defineProperty(person,"name",{  person.name; 

  3. value: "Jimmy" 

  4. });

他的3个配置项设置都为false. 这点和字面量定义需要区分开来.


2、访问器属性

这个descriptor可以算是一个tricks吧(个人观点). 平常用的时候,这个属性相当于 外部和数据属性的一个中间层. 因为你不能对访问器属性赋值...怎么说呢,他就是没有值。他只有两个函数,一个是get,一个是set。 这也是他活命的本钱了。定义访问器属性同样也是使用Object.defineProperty() 进行定义的;


  1. var people = { 

  2.     nickName:"Jimmy" 

  3. }; 

  4. Object.defineProperty(people,"name",{ 

  5.     configurable:true

  6.     //是否可以通过delete删除 

  7.     Enumerable: true

  8.     //可以通过for...in 遍历出来 

  9.     get:function(){ 

  10.         return this.nickName; 

  11.     }, 

  12.     set:function(value){ 

  13.        this.nickName = value; 

  14.     } 

  15. })


访问器属性里面的配置项里面同样有4个 items;

  1. [[Enumerable]] :(Boolean)是否可以通过for...in 循环出来 

  2.  

  3. [[Coonfigurable]] :(Boolean)是否可以通过delete关键字删除 

  4.  

  5. [[get]] : (Function)  取值函数 

  6. [[set]] : (Function) 存值函数

壮士,这个属性有什么用~


少侠磨叽, 待我来解释。


我们通常修改访问器属性来关联相关的属性变化。 是不是又觉得脑袋蒙蒙哒~


  1. var Jimmy = { 

  2.     _year:"2015",  //现在的年风 

  3.     age:17,  //现在的年龄 

  4.     burn:"1998"  //出生年份 

  5. }; 

  6. Object.defineProperty(Jimmy,"year",{ 

  7.     get:function(){ 

  8.         return this._year; 

  9.     }, 

  10.     set:function(value){ 

  11.         this._year = value; 

  12.         this.age = Number(value)-Number(this.burn); 

  13.         //同时修改年龄的值 

  14.     } 

  15. }); 

  16. Jimmy.year = "2016"

  17. //不会直接修改原来的年龄的值, 通过访问器属性改变 

  18. console.log(Jimmy.age);


这样做的好处就是做到了,数据的封装性比较好. 做到不让你访问到原始的数据类型.并且处理的时候可以对其他属性做对象的改变。 


平常在写个人信息的时候用处还是有点滴~


但是如果你有>2的属性想要写的话, 看见这样的语法,俺TMD 就疯了~~~ 所以js这门高级语言为了挽留我们这些残障人士,给我另外一个方法.Object.defineProperties()。


Object.defineProperties()

这个方法的作用,和你写字面量属性是一样的。 目的就是简化你的书写.请看栗子:

  1. Object.defineProperties(Jimmy, { 

  2.   _year: { 

  3.     value: "2015"

  4.     writable: true 

  5.   }, 

  6.   age: { 

  7.     value: "18" 

  8.   }, 

  9.   year: { 

  10.     get: function() { 

  11.       return this._year; 

  12.     }, 

  13.     set: function(value) { 

  14.       this._year = value; 

  15.       this.age = Number(value) - Number(this.burn); 

  16.       //同时修改年龄的值 

  17.     } 

  18.   } 

  19. });


Object.defineProperties(para1,para2); 第一个参数就是你要添加属性的对象. 第二个参数就是你要添加的属性。


好吧,属性的内容就介绍到这里,我还想补充一点es6关于descriptor的东西。
大家肯定有所耳闻,ECMAScript 6。


我这里不展开来讲,如果想了解的话,可以参考我的偶像 阮一峰老师 的 (http://es6.ruanyifeng.com/#docs/module)。


这里我想说一下,和访问器属性相关的class 特性;


class

class 就是类的意思,虽然混淆了js原型继承的精华,但他简单的语法也会让你忍不住爱 上她的。


同样在类中也有descriptor属性。


来个栗子:

  1. //html内容 

  2. <div>this is a div</div> 

  3. <p>this is a p</p> 

  4.  

  5. class CustomHTMLElement { 

  6.   constructor(element) { 

  7.   this.element = element; 

  8.   } 

  9.  

  10.   get html() { 

  11.   return this.element.innerHTML; 

  12.   //这里对ele设置存取值函数 

  13.   } 

  14.  

  15.   set html(value) { 

  16.   this.element.innerHTML = value; 

  17.   }} 

  18. let c= new CustomHTMLElement(document.querySelector('div')); 

  19. c.html; 

  20. //返回的是 this is a div 

  21. c.html = document.querySelector('p'); 

  22. c.html; 

  23. //返回的是 this is a p


就是这么简洁,如果下次看到class的时候,可以回头来看看 set和get 属性的含义哈~


【您可能感兴趣的文章】

一、移动端h5开发相关内容总结(四)

二、移动端h5开发相关内容总结(三)

三、如何打造黄金团队?Google招募人才的8个重点

四、[CSS篇]移动端 h5开发相关内容总结

五、[JavaScript 篇]移动端h5开发相关内容总结

六、[译]使用 Yarn 安装 Vue-cli

七、[译]取代 npm 的新利器 Yarn

八、git分支进阶

九、入职新手必知的劳动法

十、再谈移动端适配和点5像素的由来


前端圈--打造专业的前端技术会议

为web前端开发者提供技术分享和交流的平台

打造一个良好的前端圈生态,推动web标准化的发展

官网:http://fequan.com

微博:fequancom | QQ群:41378087


长按二维码关注我们

投稿:content@fequan.com

赞助合作:apply@fequan.com


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存