浅谈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 相关文章推荐
JavaScript高级程序设计 XML、Ajax 学习笔记
Sep 10 Javascript
JQquery的一些使用心得分享
Aug 01 Javascript
分享精心挑选的23款美轮美奂的jQuery 图片特效插件
Aug 14 Javascript
jQuery怎么解析Json字符串(Json格式/Json对象)
Aug 09 Javascript
jquery使用经验小结
May 20 Javascript
jquery图片滚动放大代码分享(1)
Aug 25 Javascript
CKEditor无法验证的解决方案(js验证+jQuery Validate验证)
May 09 Javascript
vue+webpack 打包文件 404 页面空白的解决方法
Feb 28 Javascript
vue中如何实现后台管理系统的权限控制的方法示例
Sep 19 Javascript
Angular2使用SVG自定义图表(条形图、折线图)组件示例
May 10 Javascript
微信小程序实现圆形进度条动画
Nov 18 Javascript
vue限制输入框只能输入8位整数和2位小数的代码
Nov 06 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程序实现支持页面后退的两种方法
2008/06/30 PHP
理解php原理的opcodes(操作码)
2010/10/26 PHP
phpmyadmin安装时提示:Warning: require_once(./libraries/common.inc.php)错误解决办法
2011/08/18 PHP
用PHP和Shell写Hadoop的MapReduce程序
2014/04/15 PHP
PHP命名空间与自动加载类详解
2018/09/04 PHP
PHP htmlentities()函数用法讲解
2019/02/25 PHP
Thinkphp框架+Layui实现图片/文件上传功能分析
2020/02/07 PHP
给moz-firefox下添加IE方法和属性
2007/04/10 Javascript
基于Jquery的文字滚动跑马灯插件(一个页面多个滚动区)
2010/07/26 Javascript
真正的JQuery.ajax传递中文参数的解决方法
2011/05/28 Javascript
JS图像无缝滚动脚本非常好用
2014/02/10 Javascript
JavaScript实现的Tween算法及缓冲特效实例代码
2015/11/03 Javascript
如何解决easyui自定义标签 datagrid edit combobox 手动输入保存不上
2015/12/26 Javascript
使用grunt合并压缩js和css文件的方法
2017/03/02 Javascript
详解Vue 普通对象数据更新与 file 对象数据更新
2017/04/26 Javascript
javascript算法之二叉搜索树的示例代码
2017/09/12 Javascript
JS无限级导航菜单实现方法
2019/01/05 Javascript
JavaScript多种滤镜算法实现代码实例
2019/12/10 Javascript
python进阶教程之循环相关函数range、enumerate、zip
2014/08/30 Python
跟老齐学Python之编写类之四再论继承
2014/10/11 Python
selenium+python实现自动登录脚本
2018/04/22 Python
Python+pyplot绘制带文本标注的柱状图方法
2019/07/08 Python
Python OpenCV图像指定区域裁剪的实现
2019/10/30 Python
使用python+poco+夜神模拟器进行自动化测试实例
2020/04/23 Python
解决tensorflow读取本地MNITS_data失败的原因
2020/06/22 Python
Python本地及虚拟解释器配置过程解析
2020/10/13 Python
浅析Python 中的 WSGI 接口和 WSGI 服务的运行
2020/12/09 Python
与世界上最好的跑步专业品牌合作:Fleet Feet
2019/03/22 全球购物
六十岁生日答谢词
2014/01/10 职场文书
商务经理岗位职责
2014/08/03 职场文书
医生见习报告范文
2014/11/03 职场文书
党的群众路线教育实践活动个人整改措施材料
2014/11/04 职场文书
2016年教师节贺卡寄语
2015/12/04 职场文书
导游词之阳朔遇龙河
2019/12/16 职场文书
Python-OpenCV教程之图像的位运算详解
2021/06/21 Python
十大经典日本动漫排行榜 海贼王第三,犬夜叉仅第八
2022/03/18 日漫