写在前面

注:这个系列是本人对js知识的一些梳理,其中不少内容来自书籍:Javascript高级程序设计第三版和JavaScript权威指南第六版,感谢它们的作者和译者。有发现什么问题的,欢迎留言指出。

1.数据属性

数据属性的4个特性:

  • Configurable:①表示能否通过delete删除属性从而重新定义,②能否修改属性的特性,③能否把属性修改为访问器属性。对象直接量里默认值true。
  • Enumerable:表示能否通过for-in循环返回属性。对象直接量里默认值true。
  • Writable:表示能否修改属性的值。对象直接量里默认值true。
  • Value:包含这个属性的数据值。对象直接量里默认值undefined。
//查看对象直接量的属性的属性特性默认值
var people = {name:'jaychou',sayName:function () {console.log(this.name);}
};
/**{value: "jaychou", writable: true, enumerable: true, configurable: true}*/
console.log(Object.getOwnPropertyDescriptor(people,'name'));
/**{value: ƒ, writable: true, enumerable: true, configurable: true}*/
console.log(Object.getOwnPropertyDescriptor(people,'sayName'));
//getOwnPropertyDescriptor对于继承属性和不存在的属性,返回undefined

要修改属性默认的特性,使用Object.defineProperty()方法,接收3个参数:对象,属性名字和描述符对象。

//修改属性默认特性:
Object.defineProperty(person,'job',{emumerable:false,//不可枚举value:'singer',writable:false,//不可写configurable:true
});
/**{name: "jaychou", sayName: ƒ, job: "singer"}*/
console.log(person);
for(var prop in person){//打印name,sayNameconsole.log(prop);
}
//会报错
try{person.job = 'director';
}catch (e) {//Cannot assign to read only property 'job' of objectconsole.log(e);
}

可以多次调用Object.defineProperty()方法修改同一个属性,但在把configurable特性设置为false之后就会有限制了:

Object.defineProperty(person,'height',{configurable:false,//不可配置writable:true,value:172
});
try{Object.defineProperty(person,'height',{configurable:true,//出错enumerable:true,//出错value:175,//正常writable:false,//writable从true变false可以,false变true也会出错});
}catch (e) {//Cannot redefine property: height at Function.definePropertyconsole.log(e);
}
try{delete person.height;
}catch (e) {//设置成不可配置后也不可删除:Cannot delete property 'height' of #<Object>console.log(e);
}

另外,调用 Object.defineProperty()方法时,如果不指定,configurable、enumerable 和 writable 特性的默认值都是 false。如果是修改已有属性,则无此限制。

2.存储器属性

存储器属性不包含数据值,只包含包含 getter 和 setter 函数(非必需)。 在读取存储器属性时,会调用 getter 函数,这个函数负责返回有效的值;在写入存储器属性时,会调用 setter 函数并传入新值,这个函数负责决定如何处理数据。4个属性特性如下:

  • Configurable:①表示能否通过delete删除属性从而重新定义,②能否修改属性的特性,③能否把属性修改为数据属性。对象直接量的默认值true
  • Enumerable:表示能否通过for-in循环返回属性。对象直接量的默认值true
  • Get:在读取属性时调用的函数。对象直接量默认值undefined
  • Set:在写入属性时调用的函数。对象直接量的默认值undefined

定义存储器属性最简单的方法是使用对象直接量语法的拓展写法:

var p = {x:3.0,y:4.0,//r是可读写的存取器属性get r(){return Math.sqrt(this.x*this.x+this.y*this.y);},set r(newValue){var oldvalue = Math.sqrt(this.x*this.x+this.y*this.y);var ratio = newValue/oldvalue;this.x *= ratio;this.y *= ratio;},//theta是只读存取器属性get theta(){return Math.atan2(this.y,this.x);}
}
console.log(p.r);
p.r = 25;

使用Object.defineProperty()方法定义存储器属性:

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;}}
})
/**{get: ƒ, set: ƒ, enumerable: false, configurable: false}*/
console.log(Object.getOwnPropertyDescriptor(book,'year'));

如例子所示,使用存储器属性的常见方式,即设置一个属性的值会导致其他属性发生变化。还有一种常见就是现在流行的类似于Vue的响应式原理,就是把data中的属性都使用defineProperty修改为存储器属性,可以监听到数据的变化。

3.定义多个属性

经常要创建或修改多个属性,这时候可以使用Object.defineProperties()方法,它接收2个参数,要添加或修改属性的对象和一个映射表,包含名称和属性描述符。

var book1 = {};
Object.defineProperties(book1,{_year:{value:'2008'},editor:{enumerable:true,value:'2'},year:{get:function () {return this._year;},set:function (newValue) {this._year = newValue;this.edition += newValue - 2004;}}
});

4.对象的可扩展性

对象的可拓展性表示是否可以给对象添加新属性。所有内置对象和自定义对象都是显式可扩展的,宿主对象的可扩展性是由Javascript引擎定义的。

1.查询对象可拓展性
var teacher = {age:25};
//true:代表可拓展
console.log(Object.isExtensible(teacher));
2.转换为不可拓展(“锁定对象”)
Object.preventExtensions(teacher);
//false
console.log(Object.isExtensible(teacher));
try{teacher.subject = 'math';
}catch (e) {//TypeError: Cannot add property subject, object is not extensibleconsole.log(e);
}

转换成不可拓展的操作是不可逆的,而且只能影响到对象本身的可拓展性,如果给一个不可拓展对象的原型添加属性,这个不可拓展对象同样会继承这些新属性。

5.密封对象

密封对象比锁定对象更高一层,除了不可拓展以外,对象的所有自身属性都设置成了不可配置的。同样密封对象操作是不可逆的。

var tea1 = {subject:'math'};
//false:代表未密封
console.log(Object.isSealed(tea1));
Object.seal(tea1);
try{Object.defineProperty(tea1,'subject',{//enumerable:false,//出错//configurable:true,//出错writable:false//和上面说的一样,writable从true变成false可以,false变成true则出错});
}catch (e) {console.log('出错..');console.log(e);
}
//true:已密封
console.log(Object.isSealed(tea1));

6.冻结对象

冻结比密封对象多的效果是:可以将它自有的所有数据属性设置为只读(如果对象的存取器属性具有setter方法,存取器属性将不受影响,仍可以通过给属性赋值调用它们)。

var tea2 = {subject:'Chinese'};
//false:代表未冻结
console.log(Object.isFrozen(tea2));
Object.freeze(tea2);
try{tea2.subject = 'math';
}catch (e) {//TypeError: Cannot assign to read only property 'subject' of objectconsole.log(e);
}
//true:已冻结
console.log(Object.isFrozen(tea2));

7.属性特性规则总结

  • 如果对象是不可拓展的,则可以编辑已有的自有属性,但不能给它添加新属性。
  • 如果属性是不可配置的,则不能修改它的可配置性和可枚举性。
  • 如果存取器属性是不可配置的,则不能修改其getter和setter方法,也不能将它转换为数据属性。
  • 如果数据属性是不可配置的,则不能将它转换为存取器属性。
  • 如果数据属性是不可配置的,则不能将它的可写性从false修改为true,但可以从true修改为false。
  • 如果数据属性是不可配置且不可写的,则不能修改它的值。然而可配置但不可写属性的值是可以修改的(做法:先将它标记为可写的,然后修改它的值,最后转换为不可写的)。

转载于:https://www.cnblogs.com/qcjay/p/9499821.html

js知识梳理1:理解对象的属性特性相关推荐

  1. Js面向对象的程序设计——理解对象

    Js面向对象的程序设计 Js面向对象的程序设计 理解对象 属性类型 Js面向对象的程序设计 理解对象 示例 : var person=new Object(); person.name="N ...

  2. js reduce 累加数组里对象某个属性的和 NaN

    js reduce 累加数组里对象某个属性的和 NaN var temp = [ { "y": 32 }, { "y": 60 }, { "y&quo ...

  3. 如何使用 JS 动态合并两个对象的属性

    作者:Abhilash Kakumanu 译者:前端小智 来源:stackak 有梦想,有干货,微信搜索 [大迁世界] 关注这个在凌晨还在刷碗的刷碗智. 本文 GitHub https://githu ...

  4. JavaScript -- 理解对象的属性

    备注:本文长期修改 目录 属性描述符 数据属性: 修改属性的一些特性 访问器属性: 设置或获取对象的某个属性的值. 操作属性特性的方法 Object.defineProperty(): 设置或修改单个 ...

  5. JS 取Json数据中对象特定属性值

    解析JSON JSON 数据 var str = '[{"a": "1","b": "2"}, {"a&quo ...

  6. Node.js知识梳理(一)——基础

    以下内容来自对<从前端到全栈>一书的学习记录~ 学习的时候用的是V16.20.0,18+之后的语法差别还是有的~ 什么是Node.js Node.js 是运行在操作系统中的 JavaScr ...

  7. JS ajax 返回的json对象 新增属性值(干货)

    $.ajax({ type:"GEt'; url:"你的地址", data:{"你的字段","字段值"} success:funt ...

  8. Node.js知识梳理之Node.js安装

    Node.js官网:nodejs.org/en/ 用户进入官网,会自动推荐适合于开发者电脑的Node.js版本,官网提示我下载适用于windows(x64)的版本.官网有两个版本LTS(长期稳定)版和 ...

  9. 【JS】1037- 面试前必备的 JavaScript 基础知识梳理总结

    1. JavaScript简介 JavaScript 最开始是专门为浏览器设计的一门语言,但是现在也被用于很多其他的环境. 如今,JavaScript 已经成为了与 HTML/CSS 完全集成的,使用 ...

  10. Js基础知识梳理系列

    小序:总是感觉自己的技术一直在原地踏步,想学习一些新的技术,但学起来很吃力,而且总是没有什么实际的收获,似乎进入了所谓的"瓶颈期".问了一些前辈是否也遇到过同样的问题,他们给我的解 ...

最新文章

  1. SQLServer学习-- SQLServer
  2. 2019年春季学期第二周作业(文件指针)
  3. 超微服务器使用IPMI安装操作系统小记
  4. 算法提高课-搜索-双向广搜 AcWing 190. 字串变换:bfs、双向bfs、queue和unordered_map
  5. 致年轻开发人员的一封信
  6. 逻辑代数01律的理解_零基础学习计算机原理:布尔逻辑和逻辑门
  7. 码码的土狼:架构的原则、范式及治理
  8. 剑指offer 09.用两个栈实现队列
  9. 新建MVC项目与发布
  10. 详解Python中函数和模块的特殊属性__annotations__
  11. jquery bind button 点击事件
  12. linux NVMe驱动总结
  13. CentOS 下编译安装AliSQL
  14. android 手机设备刷新dns
  15. Win10系统修改开机密码
  16. matlab全桥电路设计,全桥变换电路的Matlab仿真及实验装置开发.pdf
  17. 基金业绩的python分析_Python与量化多因子——聊聊Brinson业绩归因
  18. 防抖(debounce) 和 节流(throttling)的封装使用-最终发布npm
  19. python计算字符在字符串中出现的次数
  20. 数据结构-顺序表(动态分配存储空间)

热门文章

  1. 浙大计算机学院 数字媒体处理与企业智能计算实验室在哪个校区,浙大计算机学院各大实验室介绍.pdf...
  2. 风之大陆互通服务器账号,风之大陆有几个服务器?服务器互通吗?
  3. 佛说剖腹产的孩子_选择好的剖腹产时间会改变孩子的命运吗?
  4. iOS swift当app从后台切换到前台,或者锁屏后开启唤醒,app收到通知,didBecomeActiveNotification
  5. 最大似然参数估计的求解
  6. php禁言时间开发,一起来捉妖禁言时间介绍_教程一览
  7. mysql exporter怎么配置_prometheus mysqld_exporter监控mysql-5.7
  8. Morris Traversal
  9. Regularized logistic regression(正则化逻辑回归)----吴恩达机器学习
  10. linux 系统内存占用高,linux free 命令以及系统内存占用过高的处理方法