js知识梳理1:理解对象的属性特性
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,sayName
console.log(prop);
}
//会报错
try{
person.job = 'director';
}catch (e) {
//Cannot assign to read only property 'job' of object
console.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.defineProperty
console.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 extensible
console.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 object
console.log(e);
}
//true:已冻结
console.log(Object.isFrozen(tea2));
7.属性特性规则总结
- 如果对象是不可拓展的,则可以编辑已有的自有属性,但不能给它添加新属性。
- 如果属性是不可配置的,则不能修改它的可配置性和可枚举性。
- 如果存取器属性是不可配置的,则不能修改其getter和setter方法,也不能将它转换为数据属性。
- 如果数据属性是不可配置的,则不能将它转换为存取器属性。
- 如果数据属性是不可配置的,则不能将它的可写性从false修改为true,但可以从true修改为false。
- 如果数据属性是不可配置且不可写的,则不能修改它的值。然而可配置但不可写属性的值是可以修改的(做法:先将它标记为可写的,然后修改它的值,最后转换为不可写的)。
js知识梳理1:理解对象的属性特性的更多相关文章
- js如何遍历并取出对象的属性名?
js如何遍历并取出对象的属性名? dataObj = {name : su,age : 26,height : 18cm }; for(var st in dataObj) {console.dir( ...
- js知识梳理2:对象属性的操作
1.属性的查询和设置 ①基本语法 这个简单,可以通过点(.)或方括号([])运算来获取属性的值,注意点运算符后的标识符不能是保留字,方括号内的表达式必须返回字符串或返回一个可以转换成字符串的值. va ...
- js基础梳理-如何理解作用域和作用域链?
本文重点是要梳理执行上下文的生命周期中的建立作用域链,在此之前,先回顾下关于作用域的一些知识. 1.什么是作用域(scope)? 在<JavaScritp高级程序设计>中并没有找到确切的关 ...
- js知识梳理6:关于函数的要点梳理(2)(作用域链和闭包)
写在前面 注:这个系列是本人对js知识的一些梳理,其中不少内容来自书籍:Javascript高级程序设计第三版和JavaScript权威指南第六版,感谢它们的作者和译者.有发现什么问题的,欢迎留言指出 ...
- js知识梳理5:关于函数的要点梳理(1)
写在前面 注:这个系列是本人对js知识的一些梳理,其中不少内容来自书籍:Javascript高级程序设计第三版和JavaScript权威指南第六版,感谢它们的作者和译者.有发现什么问题的,欢迎留言指出 ...
- js知识梳理4.继承的模式探究
写在前面 注:这个系列是本人对js知识的一些梳理,其中不少内容来自书籍:Javascript高级程序设计第三版和JavaScript权威指南第六版,感谢它们的作者和译者.有发现什么问题的,欢迎留言指出 ...
- js知识梳理3:创建对象的模式探究
写在前面 注:这个系列是本人对js知识的一些梳理,其中不少内容来自书籍:Javascript高级程序设计第三版和JavaScript权威指南第六版,感谢它们的作者和译者.有发现什么问题的,欢迎留言指出 ...
- js中__proto__, property, prototype, 对象自身属性方法和原型中的属性方法的区别
__proto__: 这个属性是实例对象的属性,每个实例对象都有一个__proto__属性,这个属性指向实例化该实例的构造函数的原型对象(prototype). proterty:这个方法是对象的属性 ...
- JS 取Json数据中对象特定属性值
解析JSON JSON 数据 var str = '[{"a": "1","b": "2"}, {"a&quo ...
随机推荐
- Poj1151&HDU1542 Atlantis(扫描线+线段树)
题意 给定\(n\)个矩形\((x_1,y_1,x_2,y_2)\),求这\(n\)个矩形的面积并 题解 扫描线裸题,可以不用线段树维护,\(O(n^2)\)是允许的. #include < ...
- Telnet操作memcached
telnet登录 #telnet <ip> [root@c1 ~]# telnet Trying 127.0.0.1... Connected to 127.0.0.1. Escape c ...
- Linux基础系列-Day3
Vim文本编辑器 •Linux设计的重要原则是信息存储在基于文本的文件中. 注:Linux“一切皆文件”是指包含文本文件和用户不可读的二进制文件(如block设备文件) •文本文件:无格式文件,作用 ...
- BestCoder Round #65 (ZYB's Biology)
ZYB's Biology Accepts: 848 Submissions: 1199 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 13 ...
- 【BZOJ 1057】 1057: [ZJOI2007]棋盘制作
1057: [ZJOI2007]棋盘制作 Description 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源 于易经的思想,棋盘是一个8*8大小的 ...
- BZOJ 2212 [Poi2011]Tree Rotations(线段树合并)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2212 [题目大意] 给出一棵二叉树,每个叶节点上有一个权值,现在可以任意交换左右儿子, ...
- ERROR 1044: Access denied for user: 'songyan' to database 'yikexiao' 的错误。
问题描述:新买的服务器,刚安装了mysql,创建了一个用户,也忘记了给他分配了什么权限,今天在建库的时候出现了这个问题. 出错原因:度娘告诉我是因为songyan用户没有建库的权限报的错. 解决: ( ...
- NAND Flash大容量存储器K9F1G08U的坏块管理方法
转: http://www.360doc.com/content/11/0915/10/7715138_148381804.shtml 在进行数据存储的时候,我们需要保证数据的完整性,而NAND Fl ...
- 性能问题: SQL*Net message from client 等待时间太长
今天我终于自己遇到了这个问题, PO form 打不开了, 看了下 trace 发现 SQL*Net message from client 等待时间太长. 但是这不可能是网络问题, 这个环境是在我电 ...
- 1:MUI选择器组件抛出“n.getSelectedItem is not a function”异常的解决办法 2:mui三级联动 3:移动端关闭虚拟键盘
1:如下图 问题:引用了mui的地址选择的三级联动的应用在h5上的组件 百度发现别人思路对 Array 原型链方法扩充时,会抛出这个异常. 修改方法: mui.poppicker.js 第 112 行 ...