分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 网页技术

浅谈js对象之数据属性、访问器属性、Object.defineProperty方法

发布时间:2023-09-06 01:49责任编辑:蔡小小关键词:js

一、对象

  这个不用多说,常见的几种创建对象的方法有:

  1.通过构造函数创建对象,如下所示:

 function Person(){ ???????} var person = new Person();

  2.通过Object创建简单对象,例如:

 var obj = new Object();

  3.通过字面量创建对象。

 var obj = {};

  常用的一般是第一种和第三种方法。

二、属性类型

  javascript中有两种属性:数据属性和访问器属性,确切的说这两种特性是用来描述对象属性的各种特征,比如说这个对象属性的值能否被改变,因为这些特性是内部值,而javascript又不能直接访问,所以在规范中把他们放在了两对儿化括号中,例如[[Enumerable]]。下面 来看看这两种具体的内部属性。

  1.数据属性

   数据属性包含一个数据值。在这个位置可以读取和写入值,

     [[Configurable]]:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,能否把属性修改为访问器属性(这个后面会说),默认为true;

     [[Enumerable]]:用来修饰对象属性的枚举特性,表示能否通过用for in循环返回属性,默认为true;

     [[Writable]]:用来修饰对象属性值的可写特性,默认为true;

   [[Value]]:包含这个属性的数据值,访问器属性里面是没有这个特性的。默认为undefined;比如var person = {name:‘lili‘},这里设置了一个名叫name的属性,它的值是"lili", [[Value]]特性将被设置为"lili",其余的是三个特性都是默认值true。

  下面就用具体的实例来理解上面的特性。首先这里要先谈的是Object.defineProperty()方法,这个方法接收三个参数:属性所在的对象、属性的名字、和一个描述符对象(也就是上面的四个数据属性,用来描述对象属性的特性),这里要注意了,采用Object.defineProperty方法创建属性时候,数据属性[[configurable]]、[[writable]]、[[enumerable]]默认为false,这要和字面量直接声明属性时默认值相反但是如果只是用Object.defineProperty改变原来已有属性的值则没有此限制,具体看下面例子:

 var person = {};
Object.defineProperty(person,‘name‘,{ //创建name属性 ???????????value:‘lili‘, ???????}); ???????console.log(person.name); //lili ???????person.name = ‘shasha‘; //writable默认是false 不可改动属性值 ???????console.log(person.name); //lili

  修改writable的值为true可以看到,person.name的值打印出来是‘shasha‘;

 var person = {};Object.defineProperty(person,‘name‘,{//创建name属性 ???????????writable:true, ???????????value:‘lili‘, ???????}); ???????console.log(person.name); //lili ???????person.name = ‘shasha‘; //writable设置为true, 属性值被重写 ???????console.log(person.name); //shasha

 但是当person里面有属性,采用Object.defineProperty方法只是修改特性和值时,默认值都为true,具体请看下面示例:

 ???var person = {age:22}; ???????Object.defineProperty(person,‘age‘,{ ?//重新定义修改age属性 ???????????value:33, ???????}); ???????person.age = 66; ???????console.log(person.age); //66 ?说明writable此时为true,

  设置[[enumrable]]特性的规则跟[[writable]]相同,为true时才能用for in 循环遍历出属性。下面来重点看看[[Configurable]]特性的作用,例子如下:

 ??var person = {}; ???????Object.defineProperty(person,‘name‘,{ ???????????configurable:false, ???????????value:‘lili‘, ???????}); ???????console.log(person.name); //lili ???????delete person.name; ???????console.log(person.name); //lili

  把configurable设置为false,表示不能删除对象属性,对这个这个属性调用delete方法,非严格模式下什么也不会发生,严格模式下则会抛出错误,而且一旦把属性从configurable设置为false,以后就不能把它设置为true,此时在调用Object.defineProperty方法修改除writable、value之外的特性,都会导致错误,看下面例子:

 ??var person = {}; ???????Object.defineProperty(person, ‘name‘, { ???????????configurable: false, ???????????enumerable: true, ???????????writable: true, ???????????value: ‘lili‘, ???????}); ???????Object.defineProperty(person, ‘name‘, { ???????????// configurable: true, ?//会报错额! ???????????// enumerable: false, ?//会报错的! ???????????writable: false, ???????????value: ‘tangtang‘, ???????}); ???????person.name = ‘wangdachui‘; ???????console.log(person.name);//tangtang

  2.访问器属性

  访问器属性不包括数据值,它包含一对getter和setter函数,在读取访问器属性时,会调用getter函数,这个函数负责返回有效的值;在写入访问器属性时,会调用setter函数并传入新值,访问器属性有如下四个特性:

   [[Configurable]]:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,能否把属性修改为数据属性(这个后面会说),默认为true;

   [[Enumerable]]:用来修饰对象属性的枚举特性,表示能否通过用for in循环返回属性,默认为true;

   [[Get]]:在读取属性时候调用的函数,默认为undeifne;

   [[Set]]:在写入属性时候调用的函数,默认为undeifne;

  访问器属性不能直接定义,必须使用Object.defineProperty()来定义。请看下面的例子。

 ??var book = { ???????????_year: 2018, ???????????edition: 1, ???????}; ???????Object.defineProperty(book, ‘year‘, { ???????????get: function () { ???????????????alert(‘通过对象方法访问 哈哈!‘); ???????????????return this._year; ???????????}, ???????????set: function (newValue) { ???????????????if (newValue > 2004) { ???????????????????this._year = newValue; ???????????????????this.edition += newValue - 2004; ???????????????????alert(this.edition); ???????????????} ???????????} ???????}); ???????console.log(book.year) //通过对象方法访问 get函数里面alert出对应信息; ???????book.year = 2005; ???????console.log(book.edition); //2

  以上例子中,book对象有两个默认属性:_year 和 edition ,其中_year前面加了下划线,用于表示只能通过对象方法去访问这个属性,即通过get方法返回属性值。如果直接访问book.edition的值,则不会调用get方法返回。book.year=2005即是修改book的year属性值,会调用set方法,参数newValue就是设置的2005这个值,在上面例子中set函数里还改变了属性edition的值。

3.定义多个属性

  采用Object.defineProperties我们也可以为一个对象定义多个属性,这个方法有两个参数:第一个要定义属性的对象,第二个也是对象,表示要添加的多个属性和其对应的属性描述符,具体怎么添加呢,请看下面的例子:

 ??var book = {}; ???????Object.defineProperties(book,{ ???????????_year:{ ???????????????writable:true, ???????????????value:2004, ???????????}, ???????????edition:{ ???????????????writable:true, ???????????????value:1, ???????????}, ???????????year:{ ???????????????get:function(){ ???????????????????return this._year; ???????????????}, ???????????????set:function(newValue){ ???????????????????if(newValue > 2004){ ???????????????????????this._year = newValue; ???????????????????????this.edition += newValue - 2004; ???????????????????} ???????????????} ???????????} ???????});

  以上代码在book对象上定义了两个数据属性(_year和edition)和一个访问器属性(year)。

  4.读取属性的特性

  上面我们一直是在讨论如何设置属性的描述特性,那么对于数据属性和访问器属性里面的具体特性我们怎么读取呢?这里介绍另一个Object的方法:getOwnPropertyDescriptor方法,该方法接收两个参数:属性所在的对象和要读取其描述符的属性名称,它的返回是一个对象,来我们来看看具体的实例:

 ?var book = {}; ???????Object.defineProperties(book, { ???????????_year: { ???????????????writable: true, ???????????????value: 2004, ???????????}, ???????????edition: { ???????????????writable: true, ???????????????value: 1, ???????????}, ???????????year: { ???????????????get: function () { ???????????????????return this._year; ???????????????}, ???????????????set: function (newValue) { ???????????????????if (newValue > 2004) { ???????????????????????this._year = newValue; ???????????????????????this.edition += newValue - 2004; ???????????????????} ???????????????} ???????????} ???????}); ???????book.year = 2005; ???????console.log(book.edition); //2 ???????var descriptor1 = Object.getOwnPropertyDescriptor(book, ‘_year‘); ???????console.log(descriptor1.value); //2005 ???????console.log(descriptor1.configurable);//false ???????console.log(typeof descriptor1.get); //undefine ???????var descriptor2 = Object.getOwnPropertyDescriptor(book, ‘year‘); ???????console.log(descriptor2.value); //2005 ???????console.log(descriptor2.configurable);//false ???????console.log(typeof descriptor2.get); //function;

  

  

  

  

  

 

浅谈js对象之数据属性、访问器属性、Object.defineProperty方法

原文地址:https://www.cnblogs.com/homeStrong/p/8836823.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved