浅谈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 相关文章推荐
一款js和css代码压缩工具[附JAVA环境配置方法]
Apr 16 Javascript
原创javascript小游戏实现代码
Aug 19 Javascript
JQuery对id中含有特殊字符的转义处理示例
Sep 06 Javascript
探讨javascript是不是面向对象的语言
Nov 21 Javascript
JQuery与Ajax调用新浪API获取短网址的代码
Feb 07 Javascript
javascript实现的一个带下拉框功能的文本框
May 08 Javascript
JavaScript数组随机排列实现随机洗牌功能
Mar 19 Javascript
JavaScript实现的简单拖拽效果
Jun 01 Javascript
莱鸟介绍window.print()方法
Jan 06 Javascript
JavaScript中输出信息的方法(信息确认框-提示输入框-文档流输出)
Jun 12 Javascript
微信小程序 地图map实例详解
Jun 07 Javascript
一文搞懂redux在react中的初步用法
Jun 09 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
15种PHP Encoder的比较
2007/03/06 PHP
Laravel 的数据库迁移的方法
2017/07/31 PHP
SWFObject Flash js调用类
2008/07/08 Javascript
jquery dialog open后,服务器端控件失效的快速解决方法
2013/12/19 Javascript
js window.open弹出新的网页窗口
2014/01/16 Javascript
jquery获取当前点击对象的value方法
2014/02/28 Javascript
基于jquery实现的图片在各种分辨率下未知的容器内上下左右居中
2014/05/11 Javascript
jquery选择器需要注意的问题
2014/11/26 Javascript
javascript中attachEvent用法实例分析
2015/05/14 Javascript
javascript实现youku的视频代码自适应宽度
2015/05/25 Javascript
drag-and-drop实现图片浏览器预览
2015/08/06 Javascript
点击页面任何位置隐藏div的实现方法
2016/09/05 Javascript
jQuery插件form-validation-engine正则表达式操作示例
2017/02/09 Javascript
JavaScript运动框架 解决防抖动问题、悬浮对联(二)
2017/05/17 Javascript
Node.js  REPL (交互式解释器)实例详解
2017/08/06 Javascript
微信小程序 获取session_key和openid的实例
2017/08/17 Javascript
基于vue实现一个神奇的动态按钮效果
2019/05/15 Javascript
解决微信小程序云开发中获取数据库的内容为空的方法
2019/05/15 Javascript
jQuery实现提交表单时不提交隐藏div中input的方法
2019/10/08 jQuery
JavaScript 引用类型实例详解【数组、对象、严格模式等】
2020/05/13 Javascript
Python multiprocessing多进程原理与应用示例
2019/02/28 Python
Python直接赋值、浅拷贝与深度拷贝实例分析
2019/06/18 Python
Python爬虫图片懒加载技术 selenium和PhantomJS解析
2019/09/18 Python
使用Python实现Wake On Lan远程开机功能
2020/01/22 Python
python列表的逆序遍历实现
2020/04/20 Python
使用Python快速打开一个百万行级别的超大Excel文件的方法
2021/03/02 Python
HTML5 Canvas绘制五星红旗
2016/05/04 HTML / CSS
加拿大票务网站:Ticketmaster加拿大
2017/07/17 全球购物
应届生求职信写作技巧
2013/10/24 职场文书
代领报检证委托书范本
2014/10/11 职场文书
2015年幼儿园班务工作总结
2015/05/12 职场文书
赵氏孤儿观后感
2015/06/09 职场文书
2015年秋季运动会广播稿
2015/08/19 职场文书
Nebula Graph解决风控业务实践
2022/03/31 MySQL
《王者天下》第4季首话新剧照 4月9日正式开播
2022/04/07 日漫
电脑关机速度很慢怎么办 提升电脑关机速度设置教程
2022/04/08 数码科技