ES6允许在大括号内,直接写入变量和函数,作为对象的属性和方法。这样书写更加简洁。
1.属性简写
const foo = 'baz'
const obj = { foo } // { foo: 'baz' }
function f(x, y) {
return { x, y}
}
f(1, 2) // {x: 1, y: 2}
2.方法简写
const obj = {
method() {
return 'Hello'
}
}
// 等同于
const obj = {
method: function() {
return 'Hello'
}
}
JavaScript定义对象的属性,有两种方法。
// 方法一:直接用标识符作为属性名
const obj = {}
obj.foo = true // obj = { foo: false }
// 方法二:用表达式作为属性名,这时要将表达式放在方括号之内
obj['a' + 'bc'] = 123 // obj = { 'abc': 123 }
但是如果使用字面量方式定义对象(使用大括号),在ES5中只能使用方法一(标识符)定义属性。
在ES6中允许使用方法二(表达式)作为对象的属性名。
let propKey = 'foo';
let obj = {
[propKey]: true,
['a' + 'bc']: 123
};
表达式还可以用于定义方法名。
注意,属性名表达式如果是一个对象,默认情况下会自动将对象转为字符串[Object, Object],这一点一定要注意。
const keyA = {a: 1};
const keyB = {b: 2};
const myObject = {
[keyA]: 'valueA',
[keyB]: 'valueB'
};
myObject // Object {[object Object]: "valueB"}
在这段代码中,[keyA] 和[keyB]得到的都是[Object, Object],所以[keyB]
会把[keyA]
覆盖掉,而myObject
最后只有一个[object Object]
属性。
函数的name名,返回函数名。对象方法也是函数,因此也有name属性。
const person = {
sayName() {
console.log('hello!');
},
};
person.sayName.name // "sayName"
上面的代码中,方法的name属性返回了函数名(即方法名)。
如果对象的方法使用了取值函数(getter)和存值函数(setter),则name属性不是在该方法上面,而是该方法的属性的描述对象get 和set属性上面,返回值是方法名前加上get和set。(未做详细说明)
有三种特殊情况:
(new Function()).name // "anonymous"
var doSomething = function() {
// ...
};
doSomething.bind().name // "bound doSomething"
const key1 = Symbol('description');
const key2 = Symbol();
let obj = {
[key1]() {},
[key2]() {},
};
obj[key1].name // "[description]"
obj[key2].name // ""
对象的每个属性都有一个描述对象(Descriptor),用来控制该属性的行为。
Object.getOwnPropertyDescriptor()方法可以获取该属性的描述对象。
let obj = {
foo: 123
}
Object.getOwnPropertyDescriptor(obj, 'foo')
// {
// value: 123,
// writable: true,
// enumerable: true,
// configurable: true
// }
目前,有四个操作会忽略enumerable为false的属性:
ES6一共有5种方法可以遍历对象的属性。且都遵守同样的属性遍历的次序规则。
1. for…in
循环遍历对象自身的和继承的可枚举属性,不含Symbol
2. Object.keys(obj)
返回一个数组,包括对象自身的(不含继承)的所有可枚举属性的键名,不含Symbol
3. Object.getOwnPropertyNames(obj)
返回一个数组,包含对象自身的所有属性(包括不可枚举)的键名,不含Symbol
4. Object.getOwnPropertySymbols(obj)
返回一个数组,包含对象自身的所有Symbol属性的键名
5. Reflect.ownKeys(obj)
返回一个数组,包含对象自身的所有键名,不管键名是字符串还是Symbol,也不管是否可枚举
我们知道,this关键字总是指向函数所在的当前对象,ES6又新增了一个关键字super,指向当前对象的原型对象。
const proto = {
foo: 'hello'
};
const obj = {
foo: 'world',
find() {
return super.foo;
}
};
Object.setPrototypeOf(obj, proto);
obj.find() // "hello"
上面代码中,对象obj.find()
方法之中,通过super.foo
引用了原型对象proto
的foo
属性。
注意,super
关键字表示原型对象时,只能用在对象的方法之中,用在其他地方都会报错。
// 报错
const obj = {
foo: super.foo
}
// 报错
const obj = {
foo: () => super.foo
}
// 报错 只能用在简洁写法中
const obj = {
foo: function () {
return super.foo
}
}
对象的解构赋值用于从一个对象取值,相当于将目标对象自身的所有可遍历的(enumerable)、但尚未被读取的属性,分配到指定的对象上面。所有的键和它们的值,都会拷贝到新对象上面。
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
x // 1
y // 2
z // { a: 3, b: 4 }
注意事项
undefined
或null
,就会报错,因为它们无法转为对象。对象的扩展运算符(...
)用于取出参数对象的所有可遍历属性,拷贝到当前对象之中。
let z = { a: 3, b: 4 };
let n = { ...z };
n // { a: 3, b: 4 }
注意事项
Object.assign()
方法。