《javascript高级程序设计》笔记:对象数据属性和访问器属性

《javascript高级程序设计》笔记:对象数据属性和访问器属性

大家好,又见面了,我是全栈君。

1. 什么是对象

对象是无序属性的集合

创建自定义对象最简单的方式就是以字面量的形式创建对象(或创建一个Object实例),然后再为它添加属性和方法,如下所示:

var person = {
  name: "Nicholas",
  age: 29,
  sayHi: function() {
    console.log(this.name);
  }
}

但是我们需要定义对象中的某个属性能否修改,能够重写等属性,那我们应该如何定义

2. 内置属性—数据属性

Object.defineProperty()方法介绍(摘自MDN)

Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象

语法:Object.defineProperty(obj, prop, descriptor)
参数:
(1)obj:需要被操作的目标对象
(2)prop:目标对象需要定义或修改的属性的名称
(3)descriptor:将被定义或修改的属性的描述符
返回:被传递给函数的对象

2.1 configurable属性

是否可以删除目标属性或是否可以再次修改属性的特性(writable, configurable, enumerable)。默认为false

设置为true可以被删除或可以重新设置特性;
设置为false,不能被可以被删除或不可以重新设置特性,只能将writabletrue置为false

一旦把属性定义为不可配置的,就不能再把它便会可配置的,这一点很重要

主要起到数据的保护作用,决定了目标属性是否可以使用delete删除,是否可以再次设置特性

//-----------------测试目标属性是否能被删除------------------------
  var obj = {}
  
  // 第一种情况:configurable设置为true,可以被删除。
  Object.defineProperty(obj, "newKey", {
    value: "hello",
    configurable: true
  });
  // 删除属性
  delete obj.newKey;
  console.log( obj.newKey ); //undefined
  
  // 第二种情况:configurable设置为false,不能被删除。
  Object.defineProperty(obj, "newKey", {
    value: "hello",
    configurable: false
  });
  // 删除属性
  delete obj.newKey;
  console.log( obj.newKey ); //hello
  
//-----------------测试是否可以再次修改特性------------------------
  var obj = {}
  
  //第一种情况:configurable设置为false,不能再次修改特性。
  Object.defineProperty(obj, "newKey", {
    value: "hello",
    writable: false,
    enumerable: false,
    configurable: false
  });
  //重新修改特性
  Object.defineProperty(obj, "newKey", {
    value: "hello",
    writable: true,
    enumerable: true,
    configurable: true
  });
  console.log( obj.newKey ); //报错:Uncaught TypeError: Cannot redefine property: newKey
  
  //第二种情况:configurable设置为true,可以再次修改特性。
  Object.defineProperty(obj, "newKey", {
    value: "hello",
    writable: false,
    enumerable: false,
    configurable: true
  });
  //重新修改特性
  Object.defineProperty(obj, "newKey", {
    value: "hello",
    writable: true,
    enumerable: true,
    configurable: true
  });
  console.log( obj.newKey ); //hello

2.2 enumerable 属性

此属性是否可以被枚举(使用for…in或Object.keys())默认为false

设置为true可以被枚举;设置为false,不能被枚举

  var obj = {}
  
  // 第一种情况:enumerable设置为false,不能被枚举。
  Object.defineProperty(obj, "newKey", {
    value: "hello",
    writable: false,
    enumerable: false
  });
  // 枚举对象的属性
  for( var attr in obj ){
    console.log( attr );  // undefined
  }
  
  // 第二种情况:enumerable设置为true,可以被枚举。
  Object.defineProperty(obj, "newKey", {
    value: "hello",
    writable: false,
    enumerable: true
  });
  // 枚举对象的属性
  for( var attr in obj ){
  console.log( attr );  //newKey
  }

2.3 value 属性

属性对应的值,可以是任意类型的值,默认为undefined;

  var obj = {}
  // 第一种情况:不设置value属性
  Object.defineProperty(obj, "key", {});
  console.log( obj.key );  //undefined
  
  // 第二种情况:设置value属性
  Object.defineProperty(obj, "key", {
    value: "hello"
  });
  console.log( obj.key );  //hello
  
  // 同字面定义的数据值对应

2.4 writable 属性

属性的值是否可以被重写。默认为false

设置为true可以被重写;设置为false,不能被重写

  var obj = {}
  
  // 第一种情况:writable设置为false,不能重写。
  Object.defineProperty(obj, "newKey", {
    value: "hello",
    writable: false
  });
  // 更改newKey的值
  obj.newKey = "change value";
  console.log( obj.newKey );  //hello
  
  // 第二种情况:writable设置为true,可以重写
  Object.defineProperty(obj, "newKey", {
    value: "hello",
    writable: true
  });
  // 更改newKey的值
  obj.newKey = "change value";
  console.log( obj.newKey );  //change value

2.5 默认值理解(重点)

在调用 Object.defineProperty 方法给对象添加属性时,如果不指定,configurable、enumerable、writable这些值都为默认的false

==> 使用 Object.getOwnPropertyDescriptor() 方法来查看对象的内置属性

  var obj = {};
  
  // 第一种情况:使用 Object.defineProperty() 定义属性
  Object.defineProperty(obj, 'key', {
    value: "hello"
  });
  Object.getOwnPropertyDescriptor(obj, 'key');
  // {value: "hello", writable: false, enumerable: false, configurable: false}
  
  // 第二种情况:字面量方式
  obj.key = "hello";
  Object.getOwnPropertyDescriptor(obj, 'key');
  // {value: "hello", writable: true, enumerable: true, configurable: true}

2.6 数据属性总结

  1. configurable: 目标属性是否可以被删除或是否可以再次修改特性 true | false
  2. enumerable: 目标属性是否可以被枚举。true | false
  3. value: 设置属性的值 undefined
  4. writable: 值是否可以重写。true | false

3. 内置对象—访问器属性

Object.getOwnPropertyDescriptor()方法介绍(摘自MDN)

Object.getOwnPropertyDescriptor() 方法返回指定对象上一个自有属性对应的属性描述符。(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性)

语法:Object.getOwnPropertyDescriptor(obj, prop)
参数:
(1)obj:需要被操作的目标对象
(2)prop:目标对象内属性名称(String类型)
返回:如果指定的属性存在于对象上,则返回其属性描述符对象(property descriptor),否则返回 undefined

3.1 configurable 属性

参照数据属性中的configurable属性

3.2 enumerable 属性

参照数据属性中的enumerable属性

3.3 get 方法

在读取属性是调用的函数,默认值为undefined

  var obj = {}, value = "hello";
  
  Object.defineProperty(obj, 'key', {
    get: function() {
      console.log("获取obj.key的值上下文");
      return value;
    }
  });
  
  console.log(obj.key); // "获取obj.key的值上下文" hello
  obj.key = "new value";
  console.log(obj.key); // "获取obj.key的值上下文" hello

3.4 set 方法

在写入属性时调用的函数,默认值为undefined

  // 一般不会单独为属性设置set而不设置get
  var obj = {}, value = "hello";
  Object.defineProperty(obj, 'key', {
    set: function(val) {
      console.log("设置obj.key的值上下文");
    }
  });
  
  obj.key = "new value"; // "获取obj.key的值上下文"
  console.log(obj.key); // undefined

不一定非要同时指定getter和setter。只指定getter意味着属性是不能写,尝试写入属性会被忽略。在严格模式下,尝试写入只指定getter函数的属性会抛出错误。类似的,只指定setter函数的属性也不能读,否则在非严格模式下会返回undefined,而在严格模式下会抛出错误。

  var book = {
    _year: 2004,
    edition: 1 };
  Object.defineProperty(book, "year", {
      get: function() {
        return this._year;
      },
      set: function(newValue) {
        if (newValue > 2004) {
          this._year = newValue;
          this.edition += newValue - 2004;
        }
      }
  });
  book.year = 2005; alert(book.edition); //2

使用访问器属性的常见方式,即设置一个属性的值会导致其他属性发生变化

3.5 数据和视图联动(重点)

给对象o定义新的属性b,并且定义属性b的get和set方法,当o.b的时候会调用b属性的get方法,给b属性赋值的时候,会调用set方法,这就是修改数据的时候,视图会自动更新的关键前端获取数据后,需要根据数据操作dom,视图变化后,需要修改不少代码,有没有方法将数据和dom操作隔离,看一个例子

  <!-- 显示用户信息的html模版 -->
  <div>
  <p>你好,<span id='nickName'></span></p>
  <div id="introduce"></div>
  </div>
  // 视图控制器
  var userInfo = {};
  Object.defineProperty(userInfo, "nickName", {
    get: function(){
      return document.getElementById('nickName').innerHTML;
    },
    set: function(nick){
      document.getElementById('nickName').innerHTML = nick;
    }
  });
  Object.defineProperty(userInfo, "introduce", {
    get: function(){
      return document.getElementById('introduce').innerHTML;
    },
    set: function(introduce){
      document.getElementById('introduce').innerHTML = introduce;
    }
  });
  
  // 数据
  // todo 获取用户信息的代码
  // ....
  userInfo.nickName = "xxx";
  userInfo.introduce = "我是xxx,我来自云南,..."

访问器属性是实现MVVM框架的核心原理哦~

4. 定义多个属性

Object.defineProperties() 方法直接在一个对象上定义新的属性或修改现有属性,并返回该对象

语法:Object.defineProperties(obj, props)
参数:
(1)obj:在其上定义或修改属性的对象
(2)props:要定义其可枚举属性或修改的属性描述符的对象。对象中存在的属性描述符主要有数据描述符和访问器描述符两种
返回:传递给函数的对象

  var obj = {};
  Object.defineProperties(obj, {
    'property1': {
      value: true,
      writable: true
    },
    'property2': {
      value: 'Hello',
      writable: false
    }
    // etc. etc.
  });

参考:
Javascript中的Object.defineProperty
MDN Object.defineProperty
MDN Object.getOwnPropertyDescriptor

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/108068.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • redflag linux安装教程,硬盘安装REDFlag LINUX体会

    redflag linux安装教程,硬盘安装REDFlag LINUX体会我是一名LINUX的初学者,在看了许多LINUX的介绍之后,在本着大胆和心细的原则下,尝试了一回安装LINUX。现把我的一些心得和体会和大家分享,希望对一些入门级的朋友有所帮助。我装的是REDFlagLINUX,我原来的操作系统是WINXP,本着学习LINUX的和省钱至上的想法,我选择了安装WINXP和LINUX的双系统,我在网上下载了LINUX的ISO文件,先保存在随意的一个硬盘里,只要不是…

    2022年8月20日
    6
  • vc6.0控件工具栏_mfc控件隐藏

    vc6.0控件工具栏_mfc控件隐藏DevExpressVCLControls是Devexpress公司旗下最老牌的用户界面套包,所包含的控件有:数据录入、图表、数据分析、导航、布局等。该控件能帮助您创建优异的用户体验,提供高影响力的业务解决方案,并利用您现有的VCL技能为未来构建下一代应用程序DevExpressVCLv21.1.6最新版下载具体更新内容如下:此列表包括v21.1.6中已解决的所有问题。所有VCL产品T1035535–如果VCL设计器的DPI值不同于96,DevExpress在RADStud…

    2022年9月24日
    4
  • AngularJS指令「建议收藏」

    AngularJS指令「建议收藏」AngularJS指令AngularJS通过被称为指令的新属性来扩展HTML。AngularJS通过内置的指令来为应用添加功能。AngularJS允许你自定义指令。小栗子:

    在输入框中尝试输入:

    姓名:

    2022年7月25日
    14
  • 线性代数投影矩阵的定义_线性代数a和线性代数b

    线性代数投影矩阵的定义_线性代数a和线性代数bAbout投影矩阵  一个矩阵AAA既可以表示一种线性变换,又可以是一个子空间(由基张开的),还可以是一组坐标,甚是神奇。文章目录About投影矩阵一维空间的投影矩阵投影矩阵的多维推广投影的物理意义信号处理中的正交投影技术一维空间的投影矩阵  查看上图,ppp是bbb在aaa上的投影,可以发现,ppp和aaa是同向的,故可以表示为如下形式,其中xxx是标量p=axp=axp=ax  根据eee和ppp正交的条件,可以推导出x=aTbaTax=\frac{a^Tb}{a^Ta}x=aTaaT

    2022年10月4日
    2
  • MediaType介绍

    MediaType介绍MediaType媒体类型:决定浏览器将以什么形式、什么编码对资源进行解析Content-Type:也属于MediaType媒体类型,主要用于在请求头中指定资源的MediaType一、MediaType类型类型描述text/htmlHTML格式text/plain纯文本格式text/xmlXML格式image/gifgif图片格式image/jpegjpg图片格式image/pngpng图片格式application/xhtml+xm

    2022年5月26日
    37
  • 几何画板 很实用的一个软件

    几何画板 很实用的一个软件

    2021年8月21日
    94

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号