对于面向对象编程语言(如java,.net,php,python等)来说,其最大的特点在于“面向对象”,而"面向对象"较为显著的特征便是:封装,继承,多态。借助”面向对象“的这些特征,通常地,一个类大致包括三大部分:属性,方法和索引器,下面定义的一个类就包括这三大部分(.Net 语言)。

  1. public class OOClass
  2. {
  3. //定义属性
  4. private string _IDCard = "";
  5. private string _UserName = "";
  6.  
  7. //定义方法
  8. public string GetIDCard()
  9. {
  10. return _IDCard;
  11. }
  12. public string GetUserName()
  13. {
  14. return _UserName;
  15. }
  16.  
  17. //定义索引器
  18. private string Tel { get; set; }
  19. }

我们知道,JavaScript是一门”弱面向对象“编程语言,其没有”对象“和”类“(注意:我们说JavaScript一切皆对象,这里的对象与面向对象编程语言的对象含义是不同的),类是实现继承的主要技术,对象是类的实例化,如果JavaScript要想实现继承,则首先要具备类和对象的条件,只有具备了该条件,方可实现继承(其实我们知道,JavaScript的原型和原型链实现继承,我会在后面的文章中深入分析原型与原型链),那么,在JavaScript中,是 什么扮演类和对象角色呢?JavaScript对象及其属性。如果要类比,那应该是这样的关系:

一  两种典型的对象定义方式


(一)函数表达式方式

1.定义一个Person对象

  1. //定义Person对象
  2. function Person() {
  3.  
  4. }

2.为Person对象定义属性

  1. //为person对象定义属性
  2. Person._tel = "136xxx954xx";
  3. Person.name = "Alan_beijing";
  4. Person.sex = "Man";
  5. Person.Address = "Shanghai";

3.为对象定义方法

  1. //为person对象定义方法
  2. Person.tel = function () {
  3. return this._tel;
  4. }

4.测试结果

  1. //测试
  2. alert(Person.name + "," + Person.sex + "," + Person.Address + "," + Person._tel);//Alan_beijing,Man,Shanghai,136xxx954xx
  3. alert(Person.SpeakLanguage());//Chinese And English

5.完整例子Code

  1. //定义Person对象
  2. function Person() {
  3.  
  4. }
  5. //为person对象添加属性
  6. Person._tel = "136xxx954xx";
  7. Person.name = "Alan_beijing";
  8. Person.sex = "Man";
  9. Person.Address = "Shanghai";
  10. //为person对象添加方法
  11. Person.tel = function () {
  12. return this._tel;
  13. }
  14.  
  15. //测试
  16. alert(Person.name + "," + Person.sex + "," + Person.Address);//Alan_beijing,Man,Shanghai
  17. alert(Person.tel());//136xxx954xx

(二)对象字面量方式

1.定义对象同时为对象定义属性和方法

  1. var Person = {
  2. //为person对象定义属性
  3. _tel: "136xxx954xx",
  4. name: "Alan_beijing",
  5. sex: "Man",
  6. address: "Shanghai",
  7. //为person对象定义方法
  8. tel: function () {
  9. return this._tel;
  10. }
  11. }

2.测试结果

  1. //测试
  2. alert(Person.name + "," + Person.sex + "," + Person.address);//Alan_beijing,Man,Shanghai
  3. alert(Person.tel());//136xxx954xx

3.完整例子Code

  1. var Person = {
  2. //为person对象添加属性
  3. _tel: "136xxx954xx",
  4. name: "Alan_beijing",
  5. sex: "Man",
  6. address: "Shanghai",
  7. //为person对象添加方法
  8. tel: function () {
  9. return this._tel;
  10. }
  11. }
  12.  
  13. //测试
  14. alert(Person.name + "," + Person.sex + "," + Person.address);//Alan_beijing,Man,Shanghai
  15. 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()函数访问它们的四个特性值。

  1. //定义对象
  2. var Person = {
  3.  
  4. }
  5. //为对象添加属性
  6. Object.defineProperties(Person, {
  7. //为person对象添加属性
  8. _tel: {
  9. value: "136xxx954xx"
  10. },
  11. name: {
  12. value: "Alan_beijing"
  13. },
  14. sex: {
  15. value: "Man"
  16. },
  17. address: {
  18. value: "Shanghai"
  19. },
  20. //访问器
  21. telephone: {
  22. get: function () {
  23. //var strName = "name:" + name;
  24. //return strName;
  25. return this._tel;
  26. },
  27. set: function (tel) {
  28. _tel = tel;
  29. }
  30. }
  31. })
  32.  
  33. //数据属性
  34. var dataProp = Object.getOwnPropertyDescriptor(Person, "_tel");
  35. alert(dataProp.value);//136xxx954xx
  36. alert(dataProp.configurable);//false
  37. alert(dataProp.writable);//false
  38. alert(dataProp.enumerable);//false
  39. //访问器属性
  40. var visitProp = Object.getOwnPropertyDescriptor(Person, "telephone");
  41. alert(visitProp.configurable);//false
  42. alert(visitProp.enumerable);//false
  43. alert(typeof visitProp.get);//function
  44. alert(typeof visitProp.set);//function

我们再来看看下面例子:下面例子与上面例子有几点区别:

区别1:上面的属性通过defineProperties()定义在对象Person外,而下面Person对象属性都是定义在对象Persin内部的

区别2:结果不同,对于数据属性,除了[[value]]相同外,其他三个特性([[Configurable]],[[Writble]],[[Enumerable]])恰好是相反的的(上面均为false,下面均为true);对于访问器属性,除[[Configurable]]和[[Enumerable]]

属性值相反外,上面代码[[Get]]和[[Set]]能成功访问,但是下面代码显示undefined,说明索引器属性不能在对象内部定义。

  1. //定义对象
  2. var Person = {
  3. _tel: "136xxx954xx",
  4. name: "Alan_beijing",
  5. sex: "Man",
  6. telephone: {
  7. get: function () {
  8. //var strName = "name:" + name;
  9. //return strName;
  10. return this._tel;
  11. },
  12. set: function (tel) {
  13. _tel = tel;
  14. }
  15. }
  16. }
  17.  
  18. //数据属性
  19. var dataProp = Object.getOwnPropertyDescriptor(Person, "_tel");
  20. alert(dataProp.value);//136xxx954xx
  21. alert(dataProp.configurable);//true
  22. alert(dataProp.writable);//true
  23. alert(dataProp.enumerable);//true
  24.  
  25. //访问器属性
  26. var visitProp = Object.getOwnPropertyDescriptor(Person, "telephone");
  27. alert(visitProp.configurable);//true
  28. alert(visitProp.enumerable);//true
  29. alert(typeof visitProp.get);//undefined
  30. alert(typeof visitProp.set);//undefined

总结:

1.可以通过defineProperties()函数为对象定义多个属性;

2.访问器属性不能在对象内部定义,只能在对象外部定义;

3.在对象内部定义属性与通过defineProperties()函数在对象外部定义,属性特性值是相反的;

4.通过getOwnPropertyDescriptor()函数可以访问对象属性;

5.需要注意的是,访问器属性的[[Get]]和[[Set]]不是必须的;

三  对象属性基本操作


(一)添加定义属性

ECMAScript提供了definePropertie()和defineProperties()函数来为对象定义属性,这种方式是在对象外部为对象定义属性,当然,也可以在对象内部为对象定义属性(访问器属性不可在对象内部定义,只能在外部定义)

  1. //定义对象
  2. var Person = {
  3.  
  4. }
  5. //为对象添加属性
  6. Object.defineProperties(Person, {
  7. //为person对象添加属性
  8. _tel: {
  9. value: "136xxx954xx"
  10. },
  11. name: {
  12. value: "Alan_beijing"
  13. },
  14. sex: {
  15. value: "Man"
  16. },
  17. address: {
  18. value: "Shanghai"
  19. },
  20. //访问器
  21. telephone: {
  22. get: function () {
  23. //var strName = "name:" + name;
  24. //return strName;
  25. return this._tel;
  26. },
  27. set: function (tel) {
  28. _tel = tel;
  29. }
  30. }
  31. })

 (二)访问对象属性的四个特性

如下为在对象外部定义属性的访问结果,内部定义访问结果是相反的

  1. //数据属性
  2. var dataProp = Object.getOwnPropertyDescriptor(Person, "_tel");
  3. alert(dataProp.value);//136xxx954xx
  4. alert(dataProp.configurable);//false
  5. alert(dataProp.writable);//false
  6. alert(dataProp.enumerable);//false
  7. //访问器属性
  8. var visitProp = Object.getOwnPropertyDescriptor(Person, "telephone");
  9. alert(visitProp.configurable);//false
  10. alert(visitProp.enumerable);//false
  11. alert(typeof visitProp.get);//function
  12. alert(typeof visitProp.set);//function

 (三)删除/修改对象属性

如下代码,我们设置数据属性address可修改,修改成功

  1. //定义对象
  2. var Person = {
  3.  
  4. }
  5. //为对象添加属性
  6. Object.defineProperties(Person, {
  7. //为person对象添加属性
  8. _tel: {
  9. value: "136xxx954xx"
  10. },
  11. name: {
  12. value: "Alan_beijing"
  13. },
  14. sex: {
  15. value: "Man"
  16. },
  17. address: {
  18. writable: true,
  19. value: "Shanghai"
  20. },
  21. //访问器
  22. telephone: {
  23. get: function () {
  24. //var strName = "name:" + name;
  25. //return strName;
  26. return this._tel;
  27. },
  28. set: function (tel) {
  29. _tel = tel;
  30. }
  31. }
  32. })
  33.  
  34. alert(Person.address);//Shanghai
  35. Person.address = "Beijing";
  36. alert(Person.address);//Beijing

如下代码,我们先设置[[Configurable]] 只可读(false),然后尝试删除address属性,删除失败

  1. //定义对象
  2. var Person = {
  3.  
  4. }
  5. //为对象添加属性
  6. Object.defineProperties(Person, {
  7. //为person对象添加属性
  8. _tel: {
  9. value: "136xxx954xx"
  10. },
  11. name: {
  12. value: "Alan_beijing"
  13. },
  14. sex: {
  15. value: "Man"
  16. },
  17. address: {
  18. configurable: false,
  19. writable: true,
  20. value: "Shanghai"
  21. },
  22. //访问器
  23. telephone: {
  24. get: function () {
  25. //var strName = "name:" + name;
  26. //return strName;
  27. return this._tel;
  28. },
  29. set: function (tel) {
  30. _tel = tel;
  31. }
  32. }
  33. })
  34.  
  35. alert(Person.address);//Shanghai
  36. delete Person.address;
  37. alert(Person.address);//Shanghai

如下代码,我们先设置[[Configurable]]  可操作(true),然后再删除address属性,删除成功

  1. //定义对象
  2. var Person = {
  3.  
  4. }
  5. //为对象添加属性
  6. Object.defineProperties(Person, {
  7. //为person对象添加属性
  8. _tel: {
  9. value: "136xxx954xx"
  10. },
  11. name: {
  12. value: "Alan_beijing"
  13. },
  14. sex: {
  15. value: "Man"
  16. },
  17. address: {
  18. configurable: true,
  19. writable: true,
  20. value: "Shanghai"
  21. },
  22. //访问器
  23. telephone: {
  24. get: function () {
  25. //var strName = "name:" + name;
  26. //return strName;
  27. return this._tel;
  28. },
  29. set: function (tel) {
  30. _tel = tel;
  31. }
  32. }
  33. })
  34.  
  35. alert(Person.address);//Shanghai
  36. delete Person.address;
  37. alert(Person.address);//Undefined

注意:当一旦定义[[Configurable]]为false时,再也变不回去了

  1. //定义对象
  2. var Person = {
  3.  
  4. }
  5. //为对象添加属性
  6. Object.defineProperties(Person, {
  7. //为person对象添加属性
  8. _tel: {
  9. value: "136xxx954xx"
  10. },
  11. name: {
  12. value: "Alan_beijing"
  13. },
  14. sex: {
  15. value: "Man"
  16. },
  17. address: {
  18. configurable: false,
  19. writable: true,
  20. value: "Shanghai"
  21. },
  22. //访问器
  23. telephone: {
  24. get: function () {
  25. //var strName = "name:" + name;
  26. //return strName;
  27. return this._tel;
  28. },
  29. set: function (tel) {
  30. _tel = tel;
  31. }
  32. }
  33. })
  34.  
  35. Object.defineProperty(Person, "address", {
  36. configurable:true
  37. })

上述代码先将addess属性的特性[[configurable]]设置false,然后又将其修改为true,修改失败,因为[[configurable]]特性一旦设置为false,就再也不可改变。

[[configurable]]和[[writable]]区别?

前者操作属性特性,如删除属性,修改属性,更改属性类型;后者操作属性值,如更改属性值。两者没有直接关系,即不管[[configurable]]的值是怎样,一个属性的值能否可修改,是由[[writable]]决定的,而不受[[configurable]]影响。

四  参考文献


【01】JavaScript 高级程序设计(第三版)   (美)Nicholas C.Zakas 著       李松峰   曹力  译

【02】JavaScript 权威指南 (第6版)    David  Flanagan 著

五  已发布文章


  1. JavaScript之函数(上)
  2. 浅析JavaScript之数组
  3. 浅谈JavaScript之事件(上)
  4. 解析JavaScrip之属性

六  版权区


  • 感谢您的阅读,若有不足之处,欢迎指教,共同学习、共同进步。
  • 博主网址:http://www.cnblogs.com/wangjiming/。
  • 极少部分文章利用读书、参考、引用、抄袭、复制和粘贴等多种方式整合而成的,大部分为原创。
  • 如您喜欢,麻烦推荐一下;如您有新想法,欢迎提出,邮箱:2098469527@qq.com。
  • 可以转载该博客,但必须著名博客来源。

解析JavaScrip之对象属性的更多相关文章

  1. Method Resolve Order (MRO) - 类对象属性的解析顺序

    Method Resolve Order (MRO) - 类对象属性的解析顺序 Python 支持多重继承, 此时就需要解决按照何种顺序来解析属性的问题.类的继承关系在一个特殊的类属性中指定(__mr ...

  2. javascript对象属性的赋值解析

    代码如下: function Animal(){} function Dog (age){ this.name = 'fuck you' ; this.age = age } var dog = ne ...

  3. 获取对象属性类型、属性名称、属性值的研究:反射和JEXL解析引擎

    同步发布:http://www.yuanrengu.com/index.php/20170511.html 先简单介绍下反射的概念:java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所 ...

  4. Js基础知识7-JavaScript所有内置对象属性和方法汇总

    对象什么的,程序员可是有很多呢... JS三大对象 对象,是任何一个开发者都无法绕开和逃避的话题,她似乎有些深不可测,但如此伟大和巧妙的存在,一定值得你去摸索.发现.征服. 我们都知道,JavaScr ...

  5. Node对象属性

    1.Node对象属性一            * nodeName             * nodeType            * nodeValue * 使用dom解析html时候,需要ht ...

  6. AngularJS 监控对象属性:$watch和$digest

    监控对象属性:$watch和$digest $watch和$digest是相辅相成的.两者一起,构成了Angular作用域的核心:数据变化的响应.如果你学习过WPF,并基于WPF使用过一些MVVM框架 ...

  7. js 中对象--属性相关操作

    查询属性: 可以用 对象.属性 来查询属性和属性方法               或者                    对象[“属性”]  来查询属性和属性方法 演示代码: <script ...

  8. XML和对象属性互转的基类

    本人做了一个XML和对象属性互转的基类,现在放上来有兴趣拿去看一下,用法很简单,声明一个BaseConversion的子类,该子类与你想转换的对象相对应,然后覆盖基类的两个虚方法,然后在里面写元素与对 ...

  9. 前端程序员的蜕变——JS的 event 对象属性、使用实例、兼容性处理(极大提高代码效率、减少代码量)

    下面讨论一下 js 中的 Event 对象,主要从以下三个方面详细的描述(点击标题可跳转到对应部分): 1.什么是event 2.怎么用event,用他该注意什么,几个简单实际应用 3.event在不 ...

随机推荐

  1. MicroSoft CryptoAPI data/file encrypt/decrypt

    linux 用第三方库 Crypto++, 还未实战. CryptoAPI使用两种密钥:会话密钥与公共/私人密钥对.会话密钥使用相同的加密和解密密钥,这种算法较快,但必须保证密钥的安全传递.公共/私人 ...

  2. SpringBoot报错:Failed to load ApplicationContext(javax.websocket.server.ServerContainer not available)

    引起条件: WebSocket+单元测试,单元测试报错! 解决方法: SpringBootTest增加webEnvironment参数. https://docs.spring.io/spring-b ...

  3. [LeetCode] Flipping an Image 翻转图像

    Given a binary matrix A, we want to flip the image horizontally, then invert it, and return the resu ...

  4. 分割字节流为G,MB,KB的算法

    String HumanReadableFilesize(double size) { var units = new[] { "B", "KB", " ...

  5. Android Studio 全局内替换字符串

    Ctrl+Shift+R

  6. python-监控日志练习

    存在一个access.log 日志, 格式如下, 每行 以ip 地址开始: 1.需求: #1.如果同一个ip地址60s之内访问超过200次,那么就把ip加入黑名单#需求分析: #1.60秒读一次文件 ...

  7. ASP.NET Core 2.1对GDPR的支持

    欧盟的<通用数据保护条例>(General Data Protection Regulation,以下简称 GDPR)已经于 2018 年 5 月 25 日正式施行.GDPR 涵盖了包括数 ...

  8. leetcode-比特位计数

    一.题目描述 给定一个非负整数 num.对于 0 ≤ i ≤ num 范围中的每个数字 i ,计算其二进制数中的 1 的数目并将它们作为数组返回. 示例 1: 输入: 2 输出: [0,1,1] 示例 ...

  9. 阿里面试100%问到,JVM性能调优篇

    JVM 调优概述 性能定义 吞吐量 - 指不考虑 GC 引起的停顿时间或内存消耗,垃圾收集器能支撑应用达到的最高性能指标. 延迟 - 其度量标准是缩短由于垃圾啊收集引起的停顿时间或者完全消除因垃圾收集 ...

  10. js 动态生成背景图 GeoPattern

    以前有个想法,能不能用JS动态创建CANVAS绘制图案当网页背景,在网络发现有现成的别人已经实现的:GeoPattern 代码如下: <!DOCTYPE html> <html> ...