摘要:JavaScript 中对象属性的特性和常用的方法
认识对象
JavaScript 中的所有数据都可以被视为对象(一切皆对象),是一种无序的数据集合,由若干个“键值对”(key-value)构成
对象属性与方法
ECMAScript 中有两种属性:数据属性和访问器属性
数据属性
数据属性包含一个数据值的位置,在这个位置可以读取和写入值。数据属性有 4 个特性:
1.[[Configurable]]:表示能否通过delete删除属性,能否修改属性的特性,能否把属性修改为访问器属性
2.[[Enumerable]]:表示是否为枚举类型,能否通过for-in循环返回属性
3.[[Writable]]:表示能否修改属性的值(使用等号 = 赋值)
4.[[Value]]:属性的数据值,默认值为 undefined
不同方式创建对象的属性的特征默认值不同:
1 | // 方式一 |
方式一和二创建对象的属性 configurable 、 enumerable 、 writable 的默认值为 true;方式三调用 Object.defineProperty 方法时,如果不指定,则默认值都是 false
Object.defineProperty 方法接收三个参数:属性所在的对象,属性的名字和一个描述符对象。当对象原型上已经拥有一个属性,但其值无法修改(configurable 为 false),就可以使用 Object.defineProperty 方法给对象添加一个同名属性即可操作该属性
注意:
1.当属性的 configurable 为 true 、 writable 为 true,均可正常操作
2.当属性的 configurable 为 false 、 writable 为 false 时,不可操作该属性
3.当属性的 configurable 为 false 、 writable 为 true 时,使用 Object.defineProperty 方法除将 writable 改为 false 和修改 value 之外的操作都会报错, configurable 也就无法再改回 true(不可逆),但是可以使用等号(=)赋值。如果调用 delete 删除改属性,在非严格模式下什么也不会发生,而在严格模式下会报错
4.当属性的 configurable 为 true 、 writable 为 false 时,不能使用等号(=)赋值的方法修改该属性值。如果使用等号设置新值,在非严格模式下什么也不会发生,而在严格模式下会报错;但可以使用 Object.defineProperty 修改其 value
访问器属性
访问器属性不包含数据值;其包含一对 getter 和 setter 函数(两个函数都不是必须的); getter 函数负责读取,返回有效值; setter 函数负责写入,传入新值并决定如何处理数据
访问器属性也有4个特性:
1.[[Configurable]]:表示能否通过 delete 删除属性,能否修改属性的特性,能否把属性修改为数据属性
2.[[Enumerable]]:表示是否为枚举类型,能否通过 for-in 循环返回属性
3.[[Get]]:读取属性时调用,默认值为 undefined
4.[[Set]]:写入属性时调用,默认值为 undefined
不同方式创建对象的属性的特征默认值不同
1 | // 方式一 |
person 对象有两个数据属性 _year 和 age,使用方式一添加的访问器属性 year 的特性 configurable 与 enumerable 默认值为 true ;使用方式二添加的访问器属性 year 的特性 configurable 与 enumerable 默认值为 false
注意:
1.在非严格模式下,可以只指定 getter (只读不可写)或 setter (只写不可读,返回 undefined)
2.在严格模式下,只指定 getter 或 setter 会报错
对象属性操作
1.使用 Object.definePropertes 方法可通过描述符一次定义多个属性,这个方法接收两个对象参数:第一个参数对象是要添加和修改其属性的对象,第二个参数对象的属性与第一个对象中要添加或修改的属性一一对应,属性的特性默认为 false
1 | var person = {}; |
2.使用 Object.getOwnPropertyDescriptor 方法可以取得给定属性的描述符,该方法接收两个参数:属性所在的对象和要读取其描述符的属性名称,会返回一个对象。如果属性不存在或是继承自原型则返回 undefined
1 | var _year = Object.getOwnPropertyDescriptor(person, "_year"); |
3.使用 Object.propertyIsEnumerable 方法判断属性是否可以用 for-in 语句进行枚举,for-in会获取到原型链上的可枚举属性,并且其循环属性的顺序不确定
4.使用in判断对象本身或原型上有无指定的属性。使用 hasOwnProperty 方法可以判断对象本身是否有指定的属性,而不是继承原型的,与 for-in 组合可以区别是自身的还是继承原型的可枚举属性
5.使用 Object.keys 方法返回一个由给定对象的所有可枚举自身属性的属性名组成的数组, Object.getOwnPropertyNames 方法返回一个由给定对象的所有自身属性(无论是否可枚举)的属性名组成的数组
6.使用 delete 删除对象的属性,其只关注结果——只要对象没有了要删除的属性就返回 true ,哪怕原本就没有该属性
1 | "age" in person // true |
valueOf、toString 与 toLocaleString
对于不同类型的对象,有不同的 toString 和 valueOf 方法(方法被重写),如果只是单纯的调用对象,会优先使用 toString 方法,如果要与其他值运算(有运算符)会优先调用 valueOf 方法,如果无法返回原始数据类型,那么就会调用另一个方法
1.toString:
1)普通对象,返回[object Object]
2)数组,返回数组元素之间添加逗号合并成的字符串
3)函数,返回函数的定义式的字符串
4)日期对象,返回一个可读的日期和时间字符串
5)正则,返回其字面量表达式构成的字符串
1 | ({a: 1}).toString(); // '[object Object]' |
2.valueOf:
1)日期对象,返回自 1970 年 1 月 1 日到现在的毫秒数
2)其它均返回对象本身
1 | ({a: 1}).valueOf(); // {a: 1} |
注意:当有基本类型与对象进行操作时,对象会优先调用自身定义的 valueOf 方法,如果成为基本类型就返回该值,如果没有该方法或不是基本类型就调用自身定义的 toString 方法,如果还不是基本类型就调用原型链上的 toString 方法
3.toLocaleString:
1)数组,将每个数组元素转换为字符串,并将这些字符串之间以指定的分隔符拼接起来后返回
2)日期对象,返回一个以当前区域设置的长默认格式编写的日期字符串
3)其它与 toString 一致
对象的三个特性
1.原型属性[[prototype]]
对象的原型属性是一个隐藏属性,该属性指向的是这个对象的原型,一些浏览器支持对象的__proto__
属性指向其原型。
Object.create 方法可以可以接收两个参数,第一个参数指定创建对象的原型,第二个可选参数是对象本身的数据属性和访问器属性对象。
使用 Object.getPrototypeOf 方法查询原型,isPrototype 方法检测判断原型
1 | var p = {name: "niuxiaokui"}; |
2.类属性[[class]]
对象的类属性是一个字符串,用以表示对象的类型信息。使用 Object.prototype.toString 方法可以间接查询该属性,但很多对象继承的 toString 方法重写了,必须间接地调用 Function.call 方法。详细看JavaScript检测类型
3.可扩展性[[extensible]]
设置对象是否可以扩展(添加属性、方法),其值默认为 true 都是可扩展的,使用 Object.isExtensible 返回 true/false 判断
1)使用 Object.preventExtensions 方法使对象变为不可扩展,只可修改、删除
1 | Object.isExtensible(person); // true |
2)使用 Object.seal 方法使对象变为不可扩展,同时将对象所有属性的configurable
特性设置为 false
使用 Object.isSealed 方法判断是否不可扩展、修改、删除
1 | Object.isSealed(person); // false |
3)使用 Object.freeze 方法可以冻结对象,使所有属性的特性都为 false 只读
使用 Object.isFrozen 方法判断是否冻结
1 | Object.isFrozen(person); // false |
注意:Object.preventExtensions 、 Object.seal 、 Object.freeze 三种方法调用后,无法恢复原来的状态,因为没有对应可逆的方法
JavaScript深入浅出
你不知道的toString方法
Object 对象
《JavaScript高级程序设计》(第三版)第6章 面向对象的程序设计
《JavaScript权威指南》第6章 对象