浅谈JavaScript 数据属性和访问器属性


Posted in Javascript onSeptember 01, 2016

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

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

var person = new Object(); 
person.name = "Scott"; 
person.age = 24; 
person.sayName = function(){ 
  alert(person.name); 
}

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

var person = { 
  name: "Scott", 
  age: 24, 
  sayName: function(){ 
     alert(this.name);  
  } 
}

属性类型

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()方法,这个方法接收三个参数:属性所在对象、属性的名字和一个描述符对象。描述符对象只能包含上述四个特性的一个或多个。例子如下:

var person = { 
  name: "Scott"
} 
Object.defineProperty(person,"name",{ 
  writable:false; 
}) 
 
console.log(person.name);  //"Scott" 
person.name = "Evan"; 
console.log(person.name);  //"Scott"

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

var person = { 
  name: "Scott"
} 
Object.defineProperty(person,"name",{ 
  configurable:false; 
}) 
 
console.log(person.name);  //"Scott" 
delete person.name; 
console.log(person.name);  //"Scott"

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

var person = { 
  name: "Scott"
} 
Object.defineProperty(person,"name",{ 
  configurable:false; 
}) 

Object.defineProperty(person,"name",{ 
  configurable:true;  //此处会抛出错误 
})

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

•访问器属性

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

1.[[Configurable]]:默认为true。表示能否通过delete删除属性从而重新定义属性,能否修改属性特性,或者能否把属性修改为访问器属性;

2.[[Enumerable]]:默认为true。表示能否通过for-in循环返回属性;

3.[[Get]]:读取属性时调用的函数,默认为undefined;

4.[[Set]]:写入属性时调用的函数,默认为undefined。

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

var person = { 
  _name: "Scott", 
  _age: 24, 
  _tel: 86247 
}; 
//name属性为只读的 
Object.defineProperty(person,"name",{ 
  get: function(){ 
    return this._name; 
  } 
}); 
//age属性为只写不可读的 
Object.defineProperty(person,"age",{ 
  set: function(p){ 
     this._age = p; 
  } 
}); 
//tel属性为可读可写的 
Object.defineProperty(person,"tel",{ 
  get:function(){ 
     return this._tel; 
  }, 
  set: function(p){ 
     this._tel = p; 
  } 
}); 
console.log(person.name);  //"Scott" 
person.name = "Evan"; 
console.log(person.name);  //"Scott",对name属性的修改无效 
console.log(person.age);  //undefined,不可读属性 
person.age = 25; 
console.log(person._age);  //25,已经修改 
console.log(person.tel);  //"86247",可读属性 
person.tel = "13975"; 
console.log(person.tel);  //"13975",可以修改

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

定义多个属性

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

var person = { 
  _name: "Scott", 
  _age: 24, 
  _tel: 86247 
}; 
Object.defineProperties(person,{ 
  name:{ 
    get: function(){ 
      return this._name; 
    } 
  }, 
  age:{ 
    set: function(p){ 
      this._age = p; 
    } 
  }, 
  tel:{ 
    get:function(){ 
      return this._tel; 
    }, 
    set: function(p){ 
      this._tel = p; 
    } 
  } 
});

读取属性的特性

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

var person = { 
  _name: "Scott", 
  _age: 24, 
  _tel: 86247 
}; 
Object.defineProperties(person,{ 
  name:{ 
    get: function(){ 
      return this._name; 
    } 
  }, 
  age:{ 
    set: function(p){ 
      this._age = p; 
    } 
  }, 
  tel:{ 
    get:function(){ 
      return this._tel; 
    }, 
    set: function(p){ 
      this._tel = p; 
    } 
  } 
}); 
var descripter = Object.getOwnPropertyDescripter(person,"tel"); 
console.log(descripter.value);  //undefined 
console.log(descripter.enumerable);  //false 
console.log(typeof descripter.get);  //"function"

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

以上这篇浅谈JavaScript 数据属性和访问器属性就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jquery 打开窗口返回值实现代码
Mar 04 Javascript
jQuery 图片切换插件(代码比较少)
May 07 Javascript
jquery获得keycode的示例代码
Dec 30 Javascript
jquery实现带二级菜单的导航示例
Apr 28 Javascript
javascript实现禁止复制网页内容
Dec 16 Javascript
深入理解逻辑表达式的用法 与或非的用法
Jun 06 Javascript
Angularjs单选改为多选的开发过程及问题解析
Feb 17 Javascript
详解js几个绕不开的事件兼容写法
Aug 30 Javascript
关于vue编译版本引入的问题的解决
Sep 17 Javascript
layui数据表格实现重载数据表格功能(搜索功能)
Jul 27 Javascript
浅析vue cli3 封装Svgicon组件正确姿势(推荐)
Apr 27 Javascript
JS一分钟在github+Jekyll的博客中添加访问量功能的实现
Apr 03 Javascript
老生常谈JavaScript 函数表达式
Sep 01 #Javascript
Ubuntu系统下Angularjs开发环境安装
Sep 01 #Javascript
利用Angularjs和原生JS分别实现动态效果的输入框
Sep 01 #Javascript
knockoutjs动态加载外部的file作为component中的template数据源的实现方法
Sep 01 #Javascript
深入理解jQuery3.0的domManip函数
Sep 01 #Javascript
总结AngularJS开发者最常犯的十个错误
Aug 31 #Javascript
ES6记录异步函数的执行时间详解
Aug 31 #Javascript
You might like
php 上一篇,下一篇文章实现代码与原理说明
2010/05/09 PHP
介绍一些PHP判断变量的函数
2012/04/24 PHP
PHP操作文件的一些基本函数使用示例
2014/11/18 PHP
PHP之预定义接口详解
2015/07/29 PHP
php调用自己java程序的方法详解
2016/05/13 PHP
PHP中串行化用法示例
2016/11/16 PHP
PHP new static 和 new self详解
2017/02/19 PHP
laravel在中间件内生成参数并且传递到控制器中的2种姿势
2019/10/15 PHP
JS 统计时间
2021/03/09 Javascript
jquery实现图片左右间隔滚动特效(可自动播放)
2013/05/08 Javascript
Javascript字符串对象的常用方法简明版
2014/06/26 Javascript
jQuery对指定元素中指定字符串进行替换的方法
2015/03/17 Javascript
JQ选择器_选择同类元素的第N个子元素的实现方法
2016/09/08 Javascript
AngularJS学习笔记(三)数据双向绑定的简单实例
2016/11/08 Javascript
javascript循环链表之约瑟夫环的实现方法
2017/01/16 Javascript
Iscrool下拉刷新功能实现方法(推荐)
2017/06/26 Javascript
自定义类似于jQuery UI Selectable 的Vue指令v-selectable
2017/08/23 jQuery
React Native中导航组件react-navigation跨tab路由处理详解
2017/10/31 Javascript
Vue2.0生命周期的理解
2018/08/20 Javascript
BootStrap table实现表格行拖拽效果
2018/12/01 Javascript
在Vue项目中取消ESLint代码检测的步骤讲解
2019/01/27 Javascript
微信小程序如何自定义table组件
2019/06/29 Javascript
JS数组方法concat()用法实例分析
2020/01/18 Javascript
python实现自动发送报警监控邮件
2018/06/21 Python
python打包exe开机自动启动的实例(windows)
2019/06/28 Python
Python Tornado实现WEB服务器Socket服务器共存并实现交互的方法
2020/05/26 Python
Python使用正则表达式实现爬虫数据抽取
2020/08/17 Python
校园门卫岗位职责
2013/12/09 职场文书
文秘专业个人求职信
2013/12/22 职场文书
园林技术个人的自我评价
2014/01/08 职场文书
巡警年度自我鉴定
2014/02/21 职场文书
党的群众路线教育实践活动整改落实情况报告
2014/10/28 职场文书
2015年考研复习计划
2015/01/19 职场文书
Python如何导出导入所有依赖包详解
2021/06/08 Python
Python scrapy爬取起点中文网小说榜单
2021/06/13 Python
MySQL的InnoDB存储引擎的数据页结构详解
2022/03/03 MySQL