在JavaScript中对象被定义为"无序属性的集合,其属性可以包含基本值、对象或函数。"通俗点讲,我们可以把对象理解为一组一组的名值对,其中值可以是数据或函数。

  创建自定义对象通常有两种方法,第一种就是创建一个Object的实例,然后再为其添加属性和方法,例如:

  1. var person = new Object();
  2. person.name = "Scott";
  3. person.age = 24;
  4. person.sayName = function(){
  5. alert(person.name);
  6. }

  第二种方法即对象字面量法,一般推荐使用这种方法创建对象,例如:

  1. var person = {
  2. name: "Scott",
  3. age: 24,
  4. sayName: function(){
  5. alert(this.name);
  6. }
  7. }

  属性类型

  JavaScript中定义了两种不同的属性:数据属性和访问器属性。数据属性一般用于存储数据数值,而访问器属性一般进行get/set操作,不能直接存储数据数值。在ES5中,我们为了描述属性(property)的各种特征,定义了特性(attribute)。在JavaScript中不能直接访问特性,我们把它放在两对方括号中,例如[[Enumerable]]。

  • 数据属性

  数据属性主要有四个特性描述其行为:

  1. [[Configurable]]:默认为true。表示能否通过delete删除属性从而重新定义属性,能否修改属性特性,或者能否把属性修改为访问器属性;
  2. [[Enumerable]]:默认为true。表示能否通过for-in循环返回属性;
  3. [[Writable]]:默认为true。表示能否修改属性的值。
  4. [[Value]]:默认值为undefined。表示包含属性的数据值。读写属性值都从这个位置进行。

  对于上面直接在person对象上定义的属性,它们的[[Configurable]]、[[Enumerable]]、[[Writable]]特性都被默认设置为true,而[[Value]]特性被设置为特定值。如果想要修改属性默认的特性,可以使用ES5提供的Object.defineProperty()方法,这个方法接收三个参数:属性所在对象、属性的名字和一个描述符对象。描述符对象只能包含上述四个特性的一个或多个。例子如下:

  1. var person = {
  2. name: "Scott"
  3. }
  4. Object.defineProperty(person,"name",{
  5. writable:false;
  6. })
  7.  
  8. console.log(person.name); //"Scott"
  9. person.name = "Evan";
  10. console.log(person.name); //"Scott"

  将person对象name属性的特性writable设置为false,此属性的值为不可修改的,因此对该属性的复制操作会直接忽略。

  1. var person = {
  2. name: "Scott"
  3. }
  4. Object.defineProperty(person,"name",{
  5. configurable:false;
  6. })
  7.  
  8. console.log(person.name); //"Scott"
  9. delete person.name;
  10. console.log(person.name); //"Scott"

  可以看到,当把name属性的特性值configurable设置为false之后,就表示不能从对象中删除属性。但需要注意的是,当把属性定义为不可配置之后,就不能把它变回可配置的了。此时修改除writable之外的其它特性都会报错,例如:

  1. var person = {
  2. name: "Scott"
  3. }
  4. Object.defineProperty(person,"name",{
  5. configurable:false;
  6. })
  1. Object.defineProperty(person,"name",{
  2. configurable:true; //此处会抛出错误
  3. })

  也就是说,在把configurable特性修改为false之后,再修改其它特性就会有限制存在。

  • 访问器属性

  访问器属性不包含数据值。它包含一对getter和setter函数。当读取访问器属性时,会调用getter函数并返回有效值;当写入访问器属性时,会调用setter函数并传入新值,setter函数负责处理数据。该属性有四个特性:

  1. [[Configurable]]:默认为true。表示能否通过delete删除属性从而重新定义属性,能否修改属性特性,或者能否把属性修改为访问器属性;
  2. [[Enumerable]]:默认为true。表示能否通过for-in循环返回属性;
  3. [[Get]]:读取属性时调用的函数,默认为undefined;
  4. [[Set]]:写入属性时调用的函数,默认为undefined。

  访问器属性不能直接定义,必须通过Object.defineProperty()函数定义,例如:

  1. var person = {
  2. _name: "Scott",
  3. _age: 24,
  4. _tel: 86247
  5. };
  6. //name属性为只读的
  7. Object.defineProperty(person,"name",{
  8. get: function(){
  9. return this._name;
  10. }
  11. });
  12. //age属性为只写不可读的
  13. Object.defineProperty(person,"age",{
  14. set: function(p){
  15. this._age = p;
  16. }
  17. });
  18. //tel属性为可读可写的
  19. Object.defineProperty(person,"tel",{
  20. get:function(){
  21. return this._tel;
  22. },
  23. set: function(p){
  24. this._tel = p;
  25. }
  26. });
  27. console.log(person.name); //"Scott"
  28. person.name = "Evan";
  29. console.log(person.name); //"Scott",对name属性的修改无效
  30. console.log(person.age); //undefined,不可读属性
  31. person.age = 25;
  32. console.log(person._age); //25,已经修改
  33. console.log(person.tel); //"86247",可读属性
  34. person.tel = "13975";
  35. console.log(person.tel); //"13975",可以修改

  属性前面的下划线表示只能通过对象方法访问的属性。当我们使用person.name时实际上调用的是name属性的getter函数,为person.name赋值时调用的是name属性的setter函数,这样属性和访问器之间的关系就很清晰了。

  定义多个属性

  实际上ES5为我们提供了为一个对象定义多个属性的方法,即Object.defineProperties(),该函数接收两个参数,属性所在的对象以及需要修改的属性及其描述符对象组成的对象,例如把上边的例子修改为一次性定义多个属性,如下:

  1. var person = {
  2. _name: "Scott",
  3. _age: 24,
  4. _tel: 86247
  5. };
  6. Object.defineProperties(person,{
  7. name:{
  8. get: function(){
  9. return this._name;
  10. }
  11. },
  12. age:{
  13. set: function(p){
  14. this._age = p;
  15. }
  16. },
  17. tel:{
  18. get:function(){
  19. return this._tel;
  20. },
  21. set: function(p){
  22. this._tel = p;
  23. }
  24. }
  25. });

  读取属性的特性

  ES5提供了Object.getOwnPropertyDescripter()方法来获取给定属性的描述符。该方法接收两个参数:属性所在的对象和要读取其描述符的属性名称。结果会返回一个对象,如果是访问器属性,返回的对象有configuable、enumerable、get和set;如果是数据属性,这个返回对象的属性包括configuable、enumerable、writable和value。对于上面的例如,使用如下:

  1. var person = {
  2. _name: "Scott",
  3. _age: 24,
  4. _tel: 86247
  5. };
  6. Object.defineProperties(person,{
  7. name:{
  8. get: function(){
  9. return this._name;
  10. }
  11. },
  12. age:{
  13. set: function(p){
  14. this._age = p;
  15. }
  16. },
  17. tel:{
  18. get:function(){
  19. return this._tel;
  20. },
  21. set: function(p){
  22. this._tel = p;
  23. }
  24. }
  25. });
  26. var descripter = Object.getOwnPropertyDescripter(person,"tel");
  27. console.log(descripter.value); //undefined
  28. console.log(descripter.enumerable); //false
  29. console.log(typeof descripter.get); //"function"

  上面的代码中获取了person对象的tel属性,由于其是一个访问器属性,所以其value为undefined,enumerable为false,而get为指向getter函数的一个指针。

JavaScript 数据属性和访问器属性的更多相关文章

  1. JavaScript数据属性与访问器属性

    ES5中对象的属性可以分为‘数据属性’和‘访问器属性’两种. 数据属性一般用于存储数据数值,访问器属性对应的是set/get操作,不能直接存储数据值. 数据属性特性:value.writable.en ...

  2. 浅谈Javascript数据属性与访问器属性

    ES5中对象的属性可以分为‘数据属性’和‘访问器属性’两种. 数据属性一般用于存储数据数值,访问器属性对应的是set/get操作,不能直接存储数据值. 数据属性特性:value.writable.en ...

  3. JavaScript | 数据属性与访问器属性

    属性类型 数据属性 - 包含一个数据值的位置,可以读取和写入值 [writable] 是否能修改属性的值 true [enumerable] 是否通过for in 循环返回属性(是否可以被枚举) tr ...

  4. javascript数据属性和访问器属性

    var book={ _year:2004, edition:1};Object.defineProperty(book,"year",{ get:function(){ retu ...

  5. JavaScript 属性类型(数据属性和访问器属性)

    数据属性 数据属性包含一个数据值的位置.在这个位置可以读取和写入值.数据属性有 4 个描述其行为的特性. [[Configurable]]:表示能否通过 delete 删除属性从而重新定义属性,能否修 ...

  6. javascript对象属性——数据属性和访问器属性

    ECMA-262第五版在定义时,描述了属性property的各种特征,定义这些特性是为了实现javascript引擎用的,为了表示该特性是内部值,规范把它们放在了两对儿方括号中,例如[[Enumera ...

  7. JavaScript中的数据属性和访问器属性

    在学习JavaScript原型(prototype)和原型链(prototype chain)知识的时候,发现数据属性和访问器属性的重要性,通过不断的查找相关知识,浅显理解如下,若有差错,希望不吝赐教 ...

  8. Js中的数据属性和访问器属性

    Js中的数据属性和访问器属性 在javaScript中,对象的属性分为两种类型:数据属性和访问器属性. 一.数据属性 1.数据属性:它包含的是一个数据值的位置,在这可以对数据值进行读写. 2.数据属性 ...

  9. js中属性类型:数据属性与访问器属性

    js中属性类型分为两种:数据属性和访问器属性 在js中,对象都是由名值对构成的,名:就是我们所说的属性名,值就是属性对应的值(基本值.对象.方法). ECMA-262第5版定义了只有内部才用的特性,描 ...

随机推荐

  1. Mysql 学习之基础操作

    一.表复制 1.复制表结构    将表hello的结构复制一份为表hello3 2.复制数据 a.如果两张表的结构一样且你要复制所有列的数据 mysql> insert into hello3 ...

  2. C++常考面试题汇总

    c++面试题 一 用简洁的语言描述 c++ 在 c 语言的基础上开发的一种面向对象编程的语言: 应用广泛: 支持多种编程范式,面向对象编程,泛型编程,和过程化编程:广泛应用于系统开发,引擎开发:支持类 ...

  3. ASP.Net MVC 5 in Xamarin Studio 5.2

    Xamarin Studio 是一个Mono的跨平台 IDE(Integrated Development Environment),支持Wiindow和Mac,最新发布的5.2 版本支持ASP.NE ...

  4. Linux学习日记-使用EF6 Code First(四)

    一.在linux上使用EF 开发环境 VS2013+mono 3.10.0 +EF 6.1.0 先检测一下EF是不是6的 如果不是  请参阅 Linux学习日记-EF6的安装升级(三) 由于我的数据库 ...

  5. 我叫Twenty,我是要成为博客王的博客框架

    标题套用了路飞的格式,其实我想说的是大多数都不相信你的梦想,直到你快走到了. 不废话了,介绍一下twenty: 这是基于CMS框架 zerojs打造一个博客.zerojs 的架构介绍在这里http:/ ...

  6. Google Java编程库Guava介绍

    本系列想介绍下Java下开源的优秀编程库--Guava[ˈgwɑːvə].它包含了Google在Java项目中使用一些核心库,包含集合(Collections),缓存(Caching),并发编程库(C ...

  7. 工欲善其事,必先利其器 之 WPF篇: 随着开发轨迹来看高效WPF开发的工具和技巧

    之前一篇<工欲善其事,必先利其器.VS2013全攻略(安装,技巧,快捷键,插件)!> 看到很多朋友回复和支持,非常感谢,尤其是一些拍砖的喷油,感谢你们的批评,受益良多. 我第一份工作便是W ...

  8. Azure 上通过 SendGrid 发送邮件

    SendGrid 是什么? SendGrid 是架构在云端的电子邮件服务,它能提供基于事务的可靠的电子邮件传递. 并且具有可扩充性和实时分析的能力.常见的用例有: 自动回复用户的邮件 定期发送信息给用 ...

  9. 如何选择靠谱的app外包公司,2017最新资讯

    企业在外包开发app之前最纠结的问题就是如何选择一个靠谱的app外包公司.因为一个靠谱的app外包公司非常重要,完全决定了app外包开发的周期.bug.售后服务等各方面问题,可以说app开发外包团队一 ...

  10. 【Win 10应用开发】响应系统回退键的导航事件

    按例,老周今天要讲一个故事,这个故事之前老周在微博上分享过.大伙知道在8.1的时候,有一个扩展类库——NotificationExtensions,可以真TMD轻松生成通知XML模板,其实,这个类库也 ...