浅谈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 index()方法使用代码
Jun 02 Javascript
JS获取屏幕,浏览器窗口大小,网页高度宽度(实现代码)
Dec 17 Javascript
JavaScript实现点击自动选择TextArea文本的方法
Jul 02 Javascript
jquery实现可横向和竖向展开的动态下滑菜单效果
Aug 24 Javascript
两款JS脚本判断手机浏览器类型跳转WAP手机网站
Oct 16 Javascript
用js写的一个路由(简单实例)
Sep 24 Javascript
VUE JS 使用组件实现双向绑定的示例代码
Jan 10 Javascript
js实现文本上下来回滚动
Feb 03 Javascript
vue之debounce属性被移除及处理详解
Nov 13 Javascript
vue使用prop可以渲染但是打印台报错的解决方式
Nov 13 Javascript
Webpack中SplitChunksPlugin 配置参数详解
Mar 24 Javascript
Vue Mint UI mt-swipe的使用方式
Jun 05 Vue.js
老生常谈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
mysql 中InnoDB和MyISAM的区别分析小结
2008/04/15 PHP
php cache类代码(php数据缓存类)
2010/04/15 PHP
MySQL 日期时间函数常用总结
2012/06/12 PHP
PHP 如何利用phpexcel导入数据库
2013/08/24 PHP
PHP中call_user_func_array回调函数的用法示例
2016/11/26 PHP
jquery表单验证插件(jquery.validate.js)的3种使用方式
2015/03/28 Javascript
jquery插件splitScren实现页面分屏切换模板特效
2015/06/16 Javascript
简单实现异步编程promise模式
2015/07/31 Javascript
javascript实现网页背景烟花效果的方法
2015/08/06 Javascript
Jquery-data的三种用法
2017/04/18 jQuery
ES6中Class类的静态方法实例小结
2017/10/28 Javascript
React Navigation 使用中遇到的问题小结
2018/05/08 Javascript
element上传组件循环引用及简单时间倒计时的实现
2018/10/01 Javascript
JavaScript模板引擎实现原理实例详解
2018/12/14 Javascript
详解VUE前端按钮权限控制
2019/04/26 Javascript
Vue 同步异步存值取值实现案例
2020/08/05 Javascript
Flask SQLAlchemy一对一,一对多的使用方法实践
2013/02/10 Python
深入理解Python 代码优化详解
2014/10/27 Python
python链接Oracle数据库的方法
2015/06/28 Python
Python随机生成带特殊字符的密码
2016/03/02 Python
使用Python对Csv文件操作实例代码
2017/05/12 Python
利用python循环创建多个文件的方法
2018/10/25 Python
Django模型序列化返回自然主键值示例代码
2019/06/12 Python
python matplotlib 画dataframe的时间序列图实例
2019/11/20 Python
解决Jupyter无法导入已安装的 module问题
2020/04/17 Python
Interhome丹麦:在线预订度假屋和公寓
2019/07/18 全球购物
印尼在线旅游门户网站:NusaTrip
2019/11/01 全球购物
加拿大服装和鞋类零售商:Mark’s
2021/01/04 全球购物
童装店创业计划书
2014/01/09 职场文书
安全生产管理责任书
2014/04/16 职场文书
2014年教师节活动总结
2014/08/29 职场文书
群众路线组织生活会发言材料
2014/10/17 职场文书
2016大学生暑期三下乡心得体会
2016/01/23 职场文书
如何有效防止sql注入的方法
2021/05/25 SQL Server
详解Python魔法方法之描述符类
2021/05/26 Python
vue-cil之axios的二次封装与proxy反向代理使用说明
2022/04/07 Vue.js