属性的简洁表示法
ES6 允许直接写入变量和函数,作为对象的属性和方法
const foo = 'bar';
const baz = {foo};
baz // {foo: "bar"}
// 等同于
const baz = {foo: foo}; ==》 简写:const baz1 = {foo};
属性名为变量名, 属性值为变量的值,属性名总是字符串
function f(x, y) {
return {x, y};
}
// 等同于
function f(x, y) {
return {x: x, y: y};
}
//方法简写
const o = {
method() {
return "Hello!";
}
};
// 等同于
const o = {
method: function() {
return "Hello!";
}
};
如果某个方法的值是一个 Generator 函数,前面需要加上星号(*
)。
举例:
var birth = '2000/1/9'
var My= {
name:'lff',
birth,
hello(){
return 'hello'
}
}
console.log(My);
属性名表达式
ES6 允许字面量定义对象
- 基本使用
let obj = {
[propKey]: true,
['a' + 'bc']: 123
};
// {foo: true, abc: 123}
- 实例
let lastWord = 'last word';
const a = {
'first word': 'hello',
[lastWord]: 'world'
};
a['first word'] // "hello"
a[lastWord] // "world"
a['last word'] // "world"
- 表达式还可以用于定义方法名
let obj = {
['h' + 'ello']() {
return 'hi';
}
};
obj.hello() // hi
注意点 :
- 属性名表达式与简洁表示法,不能同时使用
- 属性名表达式如果是一个对象,默认情况下会自动将对象转为字符串[object Object]
方法的 name 属性
函数的name
属性,返回函数名
const person = {
sayName() {
console.log('hello!');
},
};
person.sayName.name // "sayName"
注意点 :
特例 | 返回值 |
---|---|
用了取值函数(getter)和存值函数(setter)的对象的name属性在对象的get和set属性上 对象名.get.name | get 函数名 |
bind方法创造的函数 对象名.bind().name | bound 函数名 |
Function构造函数创造的函数 (new Function()).name | anonymous |
对象的方法是 Symbol 值 | 对象的方法是一个 Symbol 值 |
属性的可枚举性和遍历
可枚举性
- for…in循环:只遍历对象自身的和继承的可枚举的属性。
- Object.keys():返回对象自身的所有可枚举的属性的键名。
- JSON.stringify():只串行化对象自身的可枚举的属性。
- Object.assign(): 忽略enumerable为false的属性,只拷贝对象自身的可枚举的属性。
Object.is()
在ES6中,Object.is()可以比较两个值是否相等,与严格相等运算符行为基本一致,不同处在于:NaN等于自身,+0不等于-0
//ES6写法
Object.is('foo','foo') //true
Object.is({},{}) //false
Object.is('+0','-0') //false
Object.is(NaN,NaN) //true
Object.assign()
Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)
var targeObject.assign方法的第一个参数是目标对象,后面的参数都是源对象t = { a: 1 };
var source1 = { b: 2 };
var source2 = { c: 3 };
Object.assign(target, source1, source2);
target // {a:1, b:2, c:3}
Object.assign方法的第一个参数是目标对象,后面的参数都是源对象
- 如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性
- 对于这种嵌套的对象,一旦遇到同名属性,Object.assign的处理方法是替换,而不是添加
- 如果该参数不是对象,则会先转成对象,然后返回
- undefined和null无法转成对象,所以如果它们作为参数,就会报错
Object.assign(undefined) // 报错
Object.assign(null) // 报错
- 非对象参数出现在源对象的位置(即非首参数),那么处理规则有所不同。首先,这些参数都会转成对象,如果无法转成对象,就会跳过。这意味着,如果undefined和null不在首参数,就不会报错
let obj = {a: 1};
Object.assign(obj, undefined) === obj // true
Object.assign(obj, null) === obj // true
- 其他类型的值(即数值、字符串和布尔值)不在首参数,也不会报错。但是,除了字符串会以数组形式,拷贝入目标对象,其他值都不会产生效果
var v1 = 'abc';
var v2 = true;
var v3 = 10;
var obj = Object.assign({}, v1, v2, v3);
console.log(obj); // { "0": "a", "1": "b", "2": "c" }
- Object.assign拷贝的属性是有限制的,只拷贝源对象的自身属性(不拷贝继承属性),也不拷贝不可枚举的属性(enumerable: false)
- 属性名为Symbol值的属性,也会被Object.assign拷贝
Object.assign({ a: 'b' }, { [Symbol('c')]: 'd' })
// { a: 'b', Symbol(c): 'd' }
- Object.assign可以用来处理数组,但是会把数组视为对象
Object.assign([1,2,3],[4,5]) //[4,5,3]
用途
- 为对象添加属性
- 为对象添加方法
- 克隆对象
- 合并多个对象
- 为属性指定默认值
规定:所有 Class 的原型的方法都是不可枚举的
遍历
var obj = {a:'1',[Symbol('b')]:2,d:4};
//添加新的属性
Object.defineProperty(obj,'c',{
value:3,
enumerable:false
});
console.log(obj); //{a: "1", d: 4, c: 3, Symbol(b): 2}
//属性遍历
//1.for...in循环,遍历对象自身和继承可枚举性
for(var i in obj){
console.log(i) //a , b
}
//2.Object.keys返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含Symbol属性)。
console.log(Object.keys(obj)); //["a", "d"]
//3.Object.getOwnPropertyNames返回一个数组,包含对象自身的所有属性(不含Symbol属性,但是包括不可枚举属性)。
console.log(Object.getOwnPropertyNames(obj)) //["a", "d", "c"]
//4.Object.getOwnPropertySymbols(obj)返回一个数组,包含对象自身的所有Symbols属性
console.log(Object.getOwnPropertySymbols(obj)) //[Symbol(b)]
//5返回一个数组,包含对象自身的所有属性,不管是属性名是Symbol或字符串,也不管是否可枚举。
console.log(Reflect.ownKeys(obj)) //["a", "d", "c", Symbol(b)]
步骤 :
- 首先遍历所有属性名为数值的属性,按照数字排序。
- 其次遍历所有属性名为字符串的属性,按照生成时间排序。
- 最后遍历所有属性名为Symbol值的属性,按照生成时间排序。
对象的扩展运算符
解构赋值
对象的解构赋值用于从一个对象取值,相当于将所有可遍历的,但尚未被读取的属性,分配到指定的对象上面。所有的键和它们的值,都会拷贝到新对象上面。
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
x // 1
y // 2
z // { a: 3, b: 4 }
解构赋值不会拷贝继承自原型对象的属性
let o1 = {a:1};
let o2 = {b:2};
o2.__proto__ = o1;
let o3 = {...o2};
o3 //{b:2}
解释说明:对象o3是o2的拷贝,但是只复制了o2自身的属性,没有复制它的原型对象o1的属性
用处 :扩展某个函数的参数,引入其他操作
function foo({a,b}){
//...
}
function wrapFoo({x,y,...restConfig}){
// 使用x和y参数进行操作
// 其余参数传给原始函数
return foo(restConfig);
}
扩展运算符
扩展运算符(…)用于取出参数对象的所有可遍历属性,拷贝到当前对象之中。
let z = {a:1,b:2};
let n = {...z};
n // {a:1, b:2}
这等同于使用Object.assign方法。
let aClone = {...a};
//等同于
let aClone = Object.assign({},a)
扩展运算符可以用于合并两个对象
let ab = { ...a, ...b };
// 等同于
let ab = Object.assign({}, a, b);
扩展运算符的参数对象之中,如果有取值函数get,这个函数是会执行的。
// 并不会抛出错误,因为x属性只是被定义,但没执行
let aWithXGetter = {
...a,
get x() {
throws new Error('not thrown yet');
}
};
// 会抛出错误,因为x属性被执行了
let runtimeError = {
...a,
...{
get x() {
throws new Error('thrown now');
}
}
};
如果扩展运算符的参数是null或undefined,这两个值会被忽略,不会报错。
let obj = {...null,...undefined}; //不报错