js之对象

119 阅读3分钟

1、属性的简洁表示

允许直接引入变量和函数,作为对象的属性和方法

var x = 1;
var obj = {
    x,
    getname(){},
    *m(){}
};

//等同于
var obj = {
    x: x,
    getname: function(){}
    m: function*(){}
}

2、属性名可以是变量或表达式

var name = 'firstname';
var obj = {
    ['a' + 'bc']: 123,
    [name]: 'li',
    ['h' + 'ello'](){}
}
//得到
obj={
    abc: 123, 
    firstname: 'li',
    hello: function(){}
}

var obj = {
    [{a:'a'}]: 'xxx'
}
//得到
obj={
    [object Object]: "xxx"
}

注意如果属性值是对象,得到'[object Object]'

3、方法的name属性

类似函数的name

(new Function()).name //"anonymous"

var doSomething = function() {};
doSomething.bind().name //"bound doSomething"


var key1 = Symbol();
var key2 = Symbol('key2');
var obj = {
    [key1](){}
    [key2](){}
}
obj[key1].name //''
obj[key2].name //'[key2]'

key1对应的 Symbol 值有描述,key2没有

4、可枚举性

var obj = {a: 'a'}
Object.getOwnPropertyDescripty(obj, 'a');
//得到
{
    value: 'a',
    writable: true,
    enumerable: true,
    configurable: true
}

(1)for...in循环只遍历对象自身的和继承的可枚举的属性

(2)Object.keys()返回对象自身的所有可枚举的属性的键名

(3)JSON.stringify()只串行化对象自身的可枚举的属性

(4)Object.assign()忽略enumerable为false的属性,只拷贝对象自身的可枚举的属性

如果enumerable=false,以上会忽略该属性。只有for...in会返回继承的属性,其他三个方法都会忽略继承的属性,只处理对象自身的属性。

总的来说,操作中引入继承的属性会让问题复杂化,大多数时候,我们只关心对象自身的属性。所以,尽量不要用for...in循环,而用Object.keys()代替

5、属性的遍历

(1)for...in循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)

(2)Object.keys返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含Symbol属性)的键名

(3)Object.getOwnPropertyNames返回一个数组,包含对象自身的所有属性((不含Symbol属性,但是包括不可枚举属性)的键名

(4)Object.getOwnPropertySymbols返回一个数组,包含对象自身的所有Symbol属性的键名

(5)Reflect.ownKeys返回一个数组,包含对象自身的所有键名,不管键名是 Symbol或字符串,也不管是否可枚举

6、super

7、对象的扩展运算符

解构赋值 对象的解构赋值用于从一个对象取值,将目标对象自身的所有可遍历的(enumerable)、但尚未被读取的属性,分配到指定的对象上面

var {x, y, ...z} = {x: 1, y: 2, a:'a', b:'b'};
x //1
y //2
z {a: 'a', b: 'b'}

注意,解构赋值的拷贝是浅拷贝,即如果一个键的值是复合类型的值(数组、对象、函数)、那么解构赋值拷贝的是这个值的引用,而不是这个值的副本。

const o = Object.create({ x: 1, y: 2 });
o.z = 3;

let { x, ...newObj } = o;
let { y, z } = newObj;
x // 1
y // undefined
z // 3

扩展运算符的解构赋值,不能复制继承自原型对象的属性。变量y和z是扩展运算符的解构赋值,只能读取对象o自身的属性,所以变量z可以赋值成功,变量y取不到值

扩展运算符

// 等同于 {...Object(1)}
{...1} // {}
// 等同于 {...Object(true)}
{...true} // {}

// 等同于 {...Object(undefined)}
{...undefined} // {}

// 等同于 {...Object(null)}
{...null} // {}

{...'hello'}
// {0: "h", 1: "e", 2: "l", 3: "l", 4: "o"}

上面的例子只是拷贝了对象实例的属性,如果想完整克隆一个对象,还拷贝对象原型的属性,可以采用下面的写法

// 写法一
const clone1 = {
  __proto__: Object.getPrototypeOf(obj),
  ...obj
};
// 写法二
const clone2 = Object.assign(
  Object.create(Object.getPrototypeOf(obj)),
  obj
);

// 写法三
const clone3 = Object.create(
  Object.getPrototypeOf(obj),
  Object.getOwnPropertyDescriptors(obj)
)