谈谈js属性的纠结往事
属性
前几天看了一下,es5的属性值,才发现里面的东西还挺深,挺坑的。原来写属性,无非就是像这样。
var People={
name:"Jimmy",
age:18
}
//或者
var People = new Object();
People.name = "Jimmy";
People.age = 18;
一个是字面量定义,一个是创建实例添加属性. 后来看了js高级程序设计才知道,js中的属性我才用了50%. 为什么这么说呢?
因为js中的属性分为数据属性和访问器属性(descriptor),而我们通常写的属性只是数据属性,而且还有一些细节比如 [[writable]],[[enumberable]],[[value]] 等一些相关的设置我们都还没有涉及。
来,我们细细谈一下。
1、数据属性
数据属性,就是我们平常定义的一些属性。
var Property = {
name:"property"
}
但是,一门高级的语言不会让你知道 你到底哪里不知道.
在es5中, 对属性进行了更细的定义, 一个数据属性有4个配置项:
[[writable]] :(Boolean) 是否可以修改属性的值
[[Enumerable]] :(Boolean)是否可以通过for...in 循环出来
[[Configurable]] :(Boolean)是否可以通过delete关键字删除
[[value]] :(xxx) 属性的内容,类型未知
如果想使用者4个配置项的话,需要使用到es5新定义的一个方法. Object.defineProperty();老板啊喂,来个栗子~
var person = {};
Object.defineProperty(person,"name",{ person.name;
writable: false,
//不能修改属性的值
value: "Nicholas",
//属性的值
configurable: false,
//不能通过delete删除该属性
Enumerable: false
//不能通过for...in 遍历出该属性
});
Object.defineProperty(para1,para2,para3)里面第一个参数就是你要修改属性的对象, 第二个就是你要修改的属性,第三个就是详细的配置项。
看完这些不是不觉得脑袋蒙蒙哒, 对的,因为我们平常用不到,而且以后也很少会用。但是对于理解js这门 OO(Object-Oriented) 为标杆的语言是非常有利的。
平常我们使用字面量定义,比如:
var people = {
name:"Jimmy"
}
js默认认为你的3个配置项(不包括value); 都是默认为true的. 如果你使用Object.defineProperty()定义(那你真是吃饱了没事,来秀技的):
var person = {};
Object.defineProperty(person,"name",{ person.name;
value: "Jimmy"
});
他的3个配置项设置都为false. 这点和字面量定义需要区分开来.
2、访问器属性
这个descriptor可以算是一个tricks吧(个人观点). 平常用的时候,这个属性相当于 外部和数据属性的一个中间层. 因为你不能对访问器属性赋值...怎么说呢,他就是没有值。他只有两个函数,一个是get,一个是set。 这也是他活命的本钱了。定义访问器属性同样也是使用Object.defineProperty() 进行定义的;
var people = {
nickName:"Jimmy"
};
Object.defineProperty(people,"name",{
configurable:true,
//是否可以通过delete删除
Enumerable: true,
//可以通过for...in 遍历出来
get:function(){
return this.nickName;
},
set:function(value){
this.nickName = value;
}
})
访问器属性里面的配置项里面同样有4个 items;
[[Enumerable]] :(Boolean)是否可以通过for...in 循环出来
[[Coonfigurable]] :(Boolean)是否可以通过delete关键字删除
[[get]] : (Function) 取值函数
[[set]] : (Function) 存值函数
壮士,这个属性有什么用~
少侠磨叽, 待我来解释。
我们通常修改访问器属性来关联相关的属性变化。 是不是又觉得脑袋蒙蒙哒~
var Jimmy = {
_year:"2015", //现在的年风
age:17, //现在的年龄
burn:"1998" //出生年份
};
Object.defineProperty(Jimmy,"year",{
get:function(){
return this._year;
},
set:function(value){
this._year = value;
this.age = Number(value)-Number(this.burn);
//同时修改年龄的值
}
});
Jimmy.year = "2016";
//不会直接修改原来的年龄的值, 通过访问器属性改变
console.log(Jimmy.age);
这样做的好处就是做到了,数据的封装性比较好. 做到不让你访问到原始的数据类型.并且处理的时候可以对其他属性做对象的改变。
平常在写个人信息的时候用处还是有点滴~
但是如果你有>2的属性想要写的话, 看见这样的语法,俺TMD 就疯了~~~ 所以js这门高级语言为了挽留我们这些残障人士,给我另外一个方法.Object.defineProperties()。
Object.defineProperties()
这个方法的作用,和你写字面量属性是一样的。 目的就是简化你的书写.请看栗子:
Object.defineProperties(Jimmy, {
_year: {
value: "2015",
writable: true
},
age: {
value: "18"
},
year: {
get: function() {
return this._year;
},
set: function(value) {
this._year = value;
this.age = Number(value) - Number(this.burn);
//同时修改年龄的值
}
}
});
Object.defineProperties(para1,para2); 第一个参数就是你要添加属性的对象. 第二个参数就是你要添加的属性。
好吧,属性的内容就介绍到这里,我还想补充一点es6关于descriptor的东西。
大家肯定有所耳闻,ECMAScript 6。
我这里不展开来讲,如果想了解的话,可以参考我的偶像 阮一峰老师 的 (http://es6.ruanyifeng.com/#docs/module)。
这里我想说一下,和访问器属性相关的class 特性;
class
class 就是类的意思,虽然混淆了js原型继承的精华,但他简单的语法也会让你忍不住爱 上她的。
同样在类中也有descriptor属性。
来个栗子:
//html内容
<div>this is a div</div>
<p>this is a p</p>
class CustomHTMLElement {
constructor(element) {
this.element = element;
}
get html() {
return this.element.innerHTML;
//这里对ele设置存取值函数
}
set html(value) {
this.element.innerHTML = value;
}}
let c= new CustomHTMLElement(document.querySelector('div'));
c.html;
//返回的是 this is a div
c.html = document.querySelector('p');
c.html;
//返回的是 this is a p
就是这么简洁,如果下次看到class的时候,可以回头来看看 set和get 属性的含义哈~
【您可能感兴趣的文章】
八、git分支进阶
前端圈--打造专业的前端技术会议
为web前端开发者提供技术分享和交流的平台
打造一个良好的前端圈生态,推动web标准化的发展
官网:http://fequan.com
微博:fequancom | QQ群:41378087
长按二维码关注我们
投稿:content@fequan.com
赞助合作:apply@fequan.com