对象的属性操作包括属性查询、属性设置、属性删除和属性继承。
属性查询
属性查询有两种方式:点运算符和方括号运算符。
【点运算符】使用点运算符访问对象属性时,属性名用一个标识符来表示,属性名必须符合变量命名规则,否则会报错。
var o = {
1: 'a',
name: 'b'
}
o.name // 'b'
o.1 // Uncaught SyntaxError: Unexpected number
【方括号运算符】使用方括号运算符访问对象属性时,属性名用一个字符串表示。方括号运算符的好处是可以用变量定义这个字符串,并且属性名可以是JavaScript无效标识符。
var o = {
1: 'a',
name: 'b'
}
var n = 'name';
o[n] // 'b'
o[1] // 'a'
方括号中的值如果不是字符串类型,默认会调用String()转型函数转化成字符串。
var o = {
1: 'a',
name: 'b'
}
o[true] // 不会报错
可计算属性名
ES6增加了可计算属性名,可以在属性名上使用[]包裹一个表达式来当作属性名。
var n = 'name'
var o = {
[n]: 'a'
}
o[n] // 'a'
o.name // 'a'
属性查询错误
当查询一个对象上不存在的属性时,会返回undefiend,不会报错。如果对象不存在的情况下查询不存在的属性会报错。
var person = {};
console.log(person.a);//undefined
console.log(person2.a); //Uncaught ReferenceError: person2 is not defined
所以获取属性值前一定要检查对象是否存在
var len = book && book.subtitle && book.subtitle.length;
属性设置
属性设置就是属性赋值,和属性查询相同,有点运算符和方括号运算符两种方法。
var o = {}
o.name = 'hello'
o['age'] = 10
console.log(o) // {name: 'hello',age: 10}
给对象设置属性前一定要检测对象是否存在。
if(book && book.subtitle) {
book.subtitle = '子标题'
}
null和undefined不是对象,所以设置属性会报错。
null.name = 'hello'; // Uncaught TypeError: Cannot set property 'name' of null
undefined.name = 'hello'; // Uncaught TypeError: Cannot set property 'name' of undefined
String、Number和Boolean类型有对应的包装类型,所以设置属性不会报错。
'a'.name = 'hello'; // 'hello'
(1).name = 'hello'; // 'hello'
true.name = 'hello'; // 'hello'
属性删除
使用delete运算符可以删除对象的属性。
var o = {name: 'hello'}
delete o.name
console.log(o.name) // undefined
console.log('name' in o) // false
把对象的属性设置为null或undefined,不能删除该属性。
var o = {name: 'hello'}
o.name = null
console.log(o.name) // null
console.log('name' in o) // true
delete运算符只能删除自有属性,不能删除继承属性。要想删除继承属性必须从定义该属性的原型对象上删除,这会影响所有继承自这个原型的对象。
var o = {name: 'hello'}
var o2 = Object.create(o)
delete o2.name
console.log(o2.name) // 'hello'
console.log('name' in o2) // true
delete操作符会返回一个布尔值:
- 删除对象属性或数组元素删除成功时,返回true
- 删除不存在的属性或非左值时,返回true
- 删除变量时,返回false,严格模式报错。
- 删除不可配置的属性时,返回false,严格模式报错。
var o = {name: 'hello'}
var arr = ['hello']
console.log(delete o.name) // true
console.log(delete arr[0]) // true
var o2 = {}
console.log(delete o.name) // true 不存在属性
console.log(delete {}) // true 非左值
console.log(delete o2) // false 左值
var str = 'hello'
console.log(delete str) // false
'use strict'
var str = 'hello'
console.log(delete str) // Delete of an unqualified identifier in strict mode.
var o = {}
Object.defineProperty(o, 'name',{configurable: false})
console.log(delete o.name) // false
'use strict'
var o = {}
Object.defineProperty(o, 'name',{configurable: false})
console.log(delete o.name) // Cannot delete property 'name' of #<Object>
【扩展】什么是左值和右值?
L-value(左值)中的L表示Location,表示可寻址,相当于地址值。
R-value(右值)中的R表示Read,表示可读取值,相当于数据值。
var a,b;
b = 0;
a = b;
上面的示例中,计算机读取b的左值(b在内存中的地址)和0的右值(就是0),把0赋值给b。然后读取b的右值(就是0)和a的左值(a在内存中的地址),把b的右值赋值给a。
b的左右值是根据他的位置判断的,在赋值符号右边表示要获取他的右值,在左边表示要获取左值。左值必须是可写入的,如果左值是常量会报错。
const a;
a = 10; // Uncaught SyntaxError: Missing initializer in const declaration
属性继承
每个对象都和一个原型对象相关联,对象从原型对象上继承属性和方法。所有通过对象字面量创建的对象都具有同一个原型对象,并且可以通过Object.prototype获得对原型对象的引用。
var o = {}
o.__proto__ === Object.prototype // true
注意: Object.prototype的原型对象是null,所以它不继承任何属性。
Object.prototype.__proto__ === null // true
对象本身具有的属性叫做自有属性,从原型对象上继承的属性叫做继承属性。
var o = {a: 1}
var o1 = Object.create(o)
o1.b = 2
console.log(o1.a) // 1 继承属性
console.log(o1.b) // 2 自有属性
【in操作符】in操作符可以判断属性是否在对象上,无论是继承还是自有属性。
var o = {a: 1}
var o1 = Object.create(o)
o1.b = 2
console.log('a' in o1) // true
console.log('b' in o1) // true
【for-in】for-in循环可以遍历对象中所有可枚举属性。
var o = {a: 1}
var o1 = Object.create(o)
o1.b = 2
for(var i in o1) {
console.log(o1[i]) // 2 1
}
【hasOwnProperty()】hasOwnProperty()方法可以确定是对象的自有属性还是继承属性。
var o = {a: 1}
var o1 = Object.create(o)
o1.b = 2
console.log(o1.hasOwnProperty('a')) // false
console.log(o1.hasOwnProperty('b')) // true
【Object.keys()】Object.keys()方法返回所有可枚举且可配置的自有属性。
var o = {a: 1}
var o1 = Object.create(o, {
c: {value: 3, enumerable: false}
})
o1.b = 2
console.log(Object.keys(o1)) // ["b"]
【Object.getOwnPropertyNames()】Object.getOwnPropertyNames()方法返回所有自有属性,包括不可枚举和不可配置属性。
var o = {a: 1}
var o1 = Object.create(o, {
c: {value: 3, enumerable: false}
})
o1.b = 2
console.log(Object.getOwnPropertyNames(o1)) // ["c", "b"]