浅谈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 不只是脚本
May 30 Javascript
javascript 支持链式调用的异步调用框架Async.Operation
Aug 04 Javascript
node.js中的fs.utimes方法使用说明
Dec 15 Javascript
jQuery中removeData()方法用法实例
Dec 27 Javascript
jQuery制作简洁的图片轮播效果
Apr 03 Javascript
浅谈node.js中async异步编程
Oct 22 Javascript
jQuery实现分隔条左右拖动功能
Nov 21 Javascript
微信小程序 网络请求(GET请求)详解
Nov 16 Javascript
Vue2组件tree实现无限级树形菜单
Mar 29 Javascript
深入浅出理解JavaScript高级定时器原理与用法
Aug 02 Javascript
js神秘的电报密码 哈弗曼编码实现
Sep 10 Javascript
node中使用shell脚本的方法步骤
Mar 23 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
当海贼王变成JOJO风
2020/03/02 日漫
新闻分类录入、显示系统
2006/10/09 PHP
用PHP和ACCESS写聊天室(八)
2006/10/09 PHP
一个php Mysql类 可以参考学习熟悉下
2009/06/21 PHP
PHP判断图片格式的七种方法小结
2013/06/03 PHP
smarty内置函数{loteral}、{ldelim}和{rdelim}用法实例
2015/01/22 PHP
PHP实现163邮箱自动发送邮件
2016/03/29 PHP
php 输出json及显示json中的中文汉字详解及实例
2016/11/09 PHP
PHP解决高并发的优化方案实例
2020/12/10 PHP
Jquery AJAX 框架的使用方法
2009/11/03 Javascript
用document.documentElement取代document.body的原因分析
2009/11/12 Javascript
基于jQuery的history历史记录插件
2010/12/11 Javascript
jQuery中prevAll()方法用法实例
2015/01/08 Javascript
jQuery实现的数值范围range2dslider选取插件特效多款代码分享
2015/08/27 Javascript
js实现鼠标点击左上角滑动菜单效果代码
2015/09/06 Javascript
angular.bind使用心得
2015/10/26 Javascript
图解js图片轮播效果
2015/12/20 Javascript
jQuery使用模式窗口实现在主页面和子页面中互相传值的方法
2016/03/01 Javascript
使用jQuery中的wrap()函数操作HTML元素的教程
2016/05/24 Javascript
谈谈对JavaScript原生拖放的深入理解
2016/09/20 Javascript
Node.js如何实现注册邮箱激活功能 (常见)
2017/07/23 Javascript
以一段代码为实例快速入门Python2.7
2015/03/31 Python
详解Python的Django框架中的templates设置
2015/05/11 Python
python版微信跳一跳游戏辅助
2018/01/11 Python
Django框架文件上传与自定义图片上传路径、上传文件名操作分析
2019/05/10 Python
python实现信号时域统计特征提取代码
2020/02/26 Python
使用keras内置的模型进行图片预测实例
2020/06/17 Python
Jupyter Notebook 安装配置与使用详解
2021/01/06 Python
HTML5 Canvas实现放大镜效果示例
2020/03/25 HTML / CSS
波兰在线体育用品商店:Hop-Sport.pl
2019/07/23 全球购物
农村婚礼主持词
2014/03/13 职场文书
教师党的群众路线对照检查材料
2014/09/24 职场文书
2014报到证办理个人委托书
2014/10/08 职场文书
《自然之道》读后感3篇
2019/12/17 职场文书
浅析python中特殊文件和特殊函数
2022/02/24 Python
原生JS实现分页
2022/04/19 Javascript