解析JavaScrip之对象属性
对于面向对象编程语言(如java,.net,php,python等)来说,其最大的特点在于“面向对象”,而"面向对象"较为显著的特征便是:封装,继承,多态。借助”面向对象“的这些特征,通常地,一个类大致包括三大部分:属性,方法和索引器,下面定义的一个类就包括这三大部分(.Net 语言)。
public class OOClass
{
//定义属性
private string _IDCard = "";
private string _UserName = ""; //定义方法
public string GetIDCard()
{
return _IDCard;
}
public string GetUserName()
{
return _UserName;
} //定义索引器
private string Tel { get; set; }
}
我们知道,JavaScript是一门”弱面向对象“编程语言,其没有”对象“和”类“(注意:我们说JavaScript一切皆对象,这里的对象与面向对象编程语言的对象含义是不同的),类是实现继承的主要技术,对象是类的实例化,如果JavaScript要想实现继承,则首先要具备类和对象的条件,只有具备了该条件,方可实现继承(其实我们知道,JavaScript的原型和原型链实现继承,我会在后面的文章中深入分析原型与原型链),那么,在JavaScript中,是 什么扮演类和对象角色呢?JavaScript对象及其属性。如果要类比,那应该是这样的关系:

一 两种典型的对象定义方式
(一)函数表达式方式
1.定义一个Person对象
//定义Person对象
function Person() { }
2.为Person对象定义属性
//为person对象定义属性
Person._tel = "136xxx954xx";
Person.name = "Alan_beijing";
Person.sex = "Man";
Person.Address = "Shanghai";
3.为对象定义方法
//为person对象定义方法
Person.tel = function () {
return this._tel;
}
4.测试结果
//测试
alert(Person.name + "," + Person.sex + "," + Person.Address + "," + Person._tel);//Alan_beijing,Man,Shanghai,136xxx954xx
alert(Person.SpeakLanguage());//Chinese And English
5.完整例子Code
//定义Person对象
function Person() { }
//为person对象添加属性
Person._tel = "136xxx954xx";
Person.name = "Alan_beijing";
Person.sex = "Man";
Person.Address = "Shanghai";
//为person对象添加方法
Person.tel = function () {
return this._tel;
} //测试
alert(Person.name + "," + Person.sex + "," + Person.Address);//Alan_beijing,Man,Shanghai
alert(Person.tel());//136xxx954xx
(二)对象字面量方式
1.定义对象同时为对象定义属性和方法
var Person = {
//为person对象定义属性
_tel: "136xxx954xx",
name: "Alan_beijing",
sex: "Man",
address: "Shanghai",
//为person对象定义方法
tel: function () {
return this._tel;
}
}
2.测试结果
//测试
alert(Person.name + "," + Person.sex + "," + Person.address);//Alan_beijing,Man,Shanghai
alert(Person.tel());//136xxx954xx
3.完整例子Code
var Person = {
//为person对象添加属性
_tel: "136xxx954xx",
name: "Alan_beijing",
sex: "Man",
address: "Shanghai",
//为person对象添加方法
tel: function () {
return this._tel;
}
}
//测试
alert(Person.name + "," + Person.sex + "," + Person.address);//Alan_beijing,Man,Shanghai
alert(Person.tel());//136xxx954xx
(三)两种方式比较
在两种典型的对象定义方式中,对象字面量定义方式是比较常用的,其常用根本原因是其采用json的格式,简洁而不繁琐。
二 对象属性种类
对象属性,从属性特性上来划分,大致可分为两大类,即数据属性和访问器属性。
(一)数据属性
数据属性具有四个基本特性,即[[Configurable]],[[Enumerable]],[[Writable]]和[[value]]。
(1)[[Configurable]]:布尔类型(true或false,默认值为true),表示能否对对象属性进行操作,大致包括如下操作:
- 删除属性
- 修改属性特性
- 修改属性类型,如将数据属性修改为访问器属性
(2)[[Enumerable]]:能否通过for..in..循环遍历
(3)[[Writable]]:能否修改属性值
(4)[[value]]:属性值
(二)访问器属性
访问器属性具有四个基本特性,即[[Configurable]],[[Enumerable]],[[Get]]和[[Set]]。
(1)[[Configurable]]:布尔类型(true或false),表示能否对对象属性进行操作,大致包括如下操作:
- 删除属性
- 修改属性特性
- 修改属性类型,如将数据属性修改为访问器属性
(2)[[Enumerable]]:能否通过for..in..循环遍历
(3)[[Get]]:对象向外提供访问对象属性的函数
(4)[[Set]]:对象向外提供设置对象属性的函数
(三)读取数据的特性
ECMAScript 5提供了Object.getOwnPropertyDescriptor()方法,通过该方法,可以取得属性特性值,该方法的原型如下:

其包含两个参数(对象和对象属性),其返回值是一个对象,如果是访问器属性,则这个对象的属性有[[Configurable]],[[Enumerable]],[[Get]],[[Set]];若对象属性为数据属性,则返回[[Configurable]],
[[Enumerable]],[[writable]]和[[value]]。 下列代码,先定义一个对象Person,然后通过ECMAScript 5提供的函数defineProperties()为该对象添加四个数据属性(_tel,name,sex和address)和一个访问器属
性(telephone),其中telephone访问器属性具有两个函数set()和get(),然后,我们通过getOwnPropertyDescriptor()函数访问它们的四个特性值。
//定义对象
var Person = { }
//为对象添加属性
Object.defineProperties(Person, {
//为person对象添加属性
_tel: {
value: "136xxx954xx"
},
name: {
value: "Alan_beijing"
},
sex: {
value: "Man"
},
address: {
value: "Shanghai"
},
//访问器
telephone: {
get: function () {
//var strName = "name:" + name;
//return strName;
return this._tel;
},
set: function (tel) {
_tel = tel;
}
}
}) //数据属性
var dataProp = Object.getOwnPropertyDescriptor(Person, "_tel");
alert(dataProp.value);//136xxx954xx
alert(dataProp.configurable);//false
alert(dataProp.writable);//false
alert(dataProp.enumerable);//false
//访问器属性
var visitProp = Object.getOwnPropertyDescriptor(Person, "telephone");
alert(visitProp.configurable);//false
alert(visitProp.enumerable);//false
alert(typeof visitProp.get);//function
alert(typeof visitProp.set);//function
我们再来看看下面例子:下面例子与上面例子有几点区别:
区别1:上面的属性通过defineProperties()定义在对象Person外,而下面Person对象属性都是定义在对象Persin内部的
区别2:结果不同,对于数据属性,除了[[value]]相同外,其他三个特性([[Configurable]],[[Writble]],[[Enumerable]])恰好是相反的的(上面均为false,下面均为true);对于访问器属性,除[[Configurable]]和[[Enumerable]]
属性值相反外,上面代码[[Get]]和[[Set]]能成功访问,但是下面代码显示undefined,说明索引器属性不能在对象内部定义。
//定义对象
var Person = {
_tel: "136xxx954xx",
name: "Alan_beijing",
sex: "Man",
telephone: {
get: function () {
//var strName = "name:" + name;
//return strName;
return this._tel;
},
set: function (tel) {
_tel = tel;
}
}
} //数据属性
var dataProp = Object.getOwnPropertyDescriptor(Person, "_tel");
alert(dataProp.value);//136xxx954xx
alert(dataProp.configurable);//true
alert(dataProp.writable);//true
alert(dataProp.enumerable);//true //访问器属性
var visitProp = Object.getOwnPropertyDescriptor(Person, "telephone");
alert(visitProp.configurable);//true
alert(visitProp.enumerable);//true
alert(typeof visitProp.get);//undefined
alert(typeof visitProp.set);//undefined
总结:
1.可以通过defineProperties()函数为对象定义多个属性;
2.访问器属性不能在对象内部定义,只能在对象外部定义;
3.在对象内部定义属性与通过defineProperties()函数在对象外部定义,属性特性值是相反的;
4.通过getOwnPropertyDescriptor()函数可以访问对象属性;
5.需要注意的是,访问器属性的[[Get]]和[[Set]]不是必须的;
三 对象属性基本操作
(一)添加定义属性
ECMAScript提供了definePropertie()和defineProperties()函数来为对象定义属性,这种方式是在对象外部为对象定义属性,当然,也可以在对象内部为对象定义属性(访问器属性不可在对象内部定义,只能在外部定义)
//定义对象
var Person = { }
//为对象添加属性
Object.defineProperties(Person, {
//为person对象添加属性
_tel: {
value: "136xxx954xx"
},
name: {
value: "Alan_beijing"
},
sex: {
value: "Man"
},
address: {
value: "Shanghai"
},
//访问器
telephone: {
get: function () {
//var strName = "name:" + name;
//return strName;
return this._tel;
},
set: function (tel) {
_tel = tel;
}
}
})
(二)访问对象属性的四个特性
如下为在对象外部定义属性的访问结果,内部定义访问结果是相反的
//数据属性
var dataProp = Object.getOwnPropertyDescriptor(Person, "_tel");
alert(dataProp.value);//136xxx954xx
alert(dataProp.configurable);//false
alert(dataProp.writable);//false
alert(dataProp.enumerable);//false
//访问器属性
var visitProp = Object.getOwnPropertyDescriptor(Person, "telephone");
alert(visitProp.configurable);//false
alert(visitProp.enumerable);//false
alert(typeof visitProp.get);//function
alert(typeof visitProp.set);//function
(三)删除/修改对象属性
如下代码,我们设置数据属性address可修改,修改成功
//定义对象
var Person = { }
//为对象添加属性
Object.defineProperties(Person, {
//为person对象添加属性
_tel: {
value: "136xxx954xx"
},
name: {
value: "Alan_beijing"
},
sex: {
value: "Man"
},
address: {
writable: true,
value: "Shanghai"
},
//访问器
telephone: {
get: function () {
//var strName = "name:" + name;
//return strName;
return this._tel;
},
set: function (tel) {
_tel = tel;
}
}
}) alert(Person.address);//Shanghai
Person.address = "Beijing";
alert(Person.address);//Beijing
如下代码,我们先设置[[Configurable]] 只可读(false),然后尝试删除address属性,删除失败
//定义对象
var Person = { }
//为对象添加属性
Object.defineProperties(Person, {
//为person对象添加属性
_tel: {
value: "136xxx954xx"
},
name: {
value: "Alan_beijing"
},
sex: {
value: "Man"
},
address: {
configurable: false,
writable: true,
value: "Shanghai"
},
//访问器
telephone: {
get: function () {
//var strName = "name:" + name;
//return strName;
return this._tel;
},
set: function (tel) {
_tel = tel;
}
}
}) alert(Person.address);//Shanghai
delete Person.address;
alert(Person.address);//Shanghai
如下代码,我们先设置[[Configurable]] 可操作(true),然后再删除address属性,删除成功
//定义对象
var Person = { }
//为对象添加属性
Object.defineProperties(Person, {
//为person对象添加属性
_tel: {
value: "136xxx954xx"
},
name: {
value: "Alan_beijing"
},
sex: {
value: "Man"
},
address: {
configurable: true,
writable: true,
value: "Shanghai"
},
//访问器
telephone: {
get: function () {
//var strName = "name:" + name;
//return strName;
return this._tel;
},
set: function (tel) {
_tel = tel;
}
}
}) alert(Person.address);//Shanghai
delete Person.address;
alert(Person.address);//Undefined
注意:当一旦定义[[Configurable]]为false时,再也变不回去了
//定义对象
var Person = { }
//为对象添加属性
Object.defineProperties(Person, {
//为person对象添加属性
_tel: {
value: "136xxx954xx"
},
name: {
value: "Alan_beijing"
},
sex: {
value: "Man"
},
address: {
configurable: false,
writable: true,
value: "Shanghai"
},
//访问器
telephone: {
get: function () {
//var strName = "name:" + name;
//return strName;
return this._tel;
},
set: function (tel) {
_tel = tel;
}
}
}) Object.defineProperty(Person, "address", {
configurable:true
})
上述代码先将addess属性的特性[[configurable]]设置false,然后又将其修改为true,修改失败,因为[[configurable]]特性一旦设置为false,就再也不可改变。

[[configurable]]和[[writable]]区别?
前者操作属性特性,如删除属性,修改属性,更改属性类型;后者操作属性值,如更改属性值。两者没有直接关系,即不管[[configurable]]的值是怎样,一个属性的值能否可修改,是由[[writable]]决定的,而不受[[configurable]]影响。
四 参考文献
【01】JavaScript 高级程序设计(第三版) (美)Nicholas C.Zakas 著 李松峰 曹力 译
【02】JavaScript 权威指南 (第6版) David Flanagan 著
五 已发布文章
六 版权区
- 感谢您的阅读,若有不足之处,欢迎指教,共同学习、共同进步。
- 博主网址:http://www.cnblogs.com/wangjiming/。
- 极少部分文章利用读书、参考、引用、抄袭、复制和粘贴等多种方式整合而成的,大部分为原创。
- 如您喜欢,麻烦推荐一下;如您有新想法,欢迎提出,邮箱:2098469527@qq.com。
- 可以转载该博客,但必须著名博客来源。
解析JavaScrip之对象属性的更多相关文章
- Method Resolve Order (MRO) - 类对象属性的解析顺序
Method Resolve Order (MRO) - 类对象属性的解析顺序 Python 支持多重继承, 此时就需要解决按照何种顺序来解析属性的问题.类的继承关系在一个特殊的类属性中指定(__mr ...
- javascript对象属性的赋值解析
代码如下: function Animal(){} function Dog (age){ this.name = 'fuck you' ; this.age = age } var dog = ne ...
- 获取对象属性类型、属性名称、属性值的研究:反射和JEXL解析引擎
同步发布:http://www.yuanrengu.com/index.php/20170511.html 先简单介绍下反射的概念:java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所 ...
- Js基础知识7-JavaScript所有内置对象属性和方法汇总
对象什么的,程序员可是有很多呢... JS三大对象 对象,是任何一个开发者都无法绕开和逃避的话题,她似乎有些深不可测,但如此伟大和巧妙的存在,一定值得你去摸索.发现.征服. 我们都知道,JavaScr ...
- Node对象属性
1.Node对象属性一 * nodeName * nodeType * nodeValue * 使用dom解析html时候,需要ht ...
- AngularJS 监控对象属性:$watch和$digest
监控对象属性:$watch和$digest $watch和$digest是相辅相成的.两者一起,构成了Angular作用域的核心:数据变化的响应.如果你学习过WPF,并基于WPF使用过一些MVVM框架 ...
- js 中对象--属性相关操作
查询属性: 可以用 对象.属性 来查询属性和属性方法 或者 对象[“属性”] 来查询属性和属性方法 演示代码: <script ...
- XML和对象属性互转的基类
本人做了一个XML和对象属性互转的基类,现在放上来有兴趣拿去看一下,用法很简单,声明一个BaseConversion的子类,该子类与你想转换的对象相对应,然后覆盖基类的两个虚方法,然后在里面写元素与对 ...
- 前端程序员的蜕变——JS的 event 对象属性、使用实例、兼容性处理(极大提高代码效率、减少代码量)
下面讨论一下 js 中的 Event 对象,主要从以下三个方面详细的描述(点击标题可跳转到对应部分): 1.什么是event 2.怎么用event,用他该注意什么,几个简单实际应用 3.event在不 ...
随机推荐
- jQuery与其它js库共用
<script src="js/zepto.min.js"></script>//其它js库<script src="http://comm ...
- Centos安装配置Tomcat,并部署web应用
一.安装JDK并配置环境变量 1.检查和删除系统预装jdk //如果操作系统不是最小安装,会默认安装openjdk#rpm -qa | grep java //删除系统预装jdk,可以一条命令直接删除 ...
- Tensor基本操作
Tensor(张量) 1.Tensor,又名张量,从工程角度来说,可简单地认为它就是一个数组,且支持高效的科学计算.它可以是一个数(标量).一维数组(向量).二维数组(矩阵)或更高维的数组(高阶数组) ...
- git教程——工作流程
Git 工作流程 本章节我们将为大家介绍 Git 的工作流程. 一般工作流程如下: 克隆 Git 资源作为工作目录. 在克隆的资源上添加或修改文件. 如果其他人修改了,你可以更新资源. 在提交前查看修 ...
- swust oj 1013
哈希表(开放定址法处理冲突) 1000(ms) 10000(kb) 2698 / 6177 采用除留余数法(H(key)=key %n)建立长度为n的哈希表,处理冲突用开放定址法的线性探测. 输入 第 ...
- Flutter
2015年, Google 内部开始测试另一种高性能的编程方式,那就 Google 的 Sky 项目.Sky 项目使用网页开发语言Dart开发原生Android 应用,强调应用的运行速度和与 Web ...
- requirejs + sass 实现的前端及 grunt 自动化构建
对于 现在的 vue . react .webpack 来说也许有点旧了,有时候,越简单的技术越可靠,备份一下 module.exports = function(grunt) { // Projec ...
- ABP入门系列(4)——创建应用服务
ABP入门系列目录--学习Abp框架之实操演练 一.解释下应用服务层 应用服务用于将领域(业务)逻辑暴露给展现层.展现层通过传入DTO(数据传输对象)参数来调用应用服务,而应用服务通过领域对象来执行相 ...
- Android单元测试之四:仪器化测试
Android单元测试之四:仪器化测试 仪器化测试 在某些情况下,虽然可以通过模拟的手段来隔离 Android 依赖,但代价很大,这种情况下可以考虑仪器化的单元测试,有助于减少编写和维护模拟代码所需的 ...
- [Swift]LeetCode128. 最长连续序列 | Longest Consecutive Sequence
Given an unsorted array of integers, find the length of the longest consecutive elements sequence. Y ...
[[configurable]]和[[writable]]区别?