重要知识点:
属性
在对象中,属性名永远都是字符串。如果你使用 string(字面量)以外的其他值作为属性 名,那它首先会被转换为一个字符串。即使是数字也不例外,虽然在数组下标中使用的的 确是数字,但是在对象属性名中数字会被转换成字符串,所以当心不要搞混对象和数组中 数字的用法:
1. Object.assign()
浅复制, 会遍历一个或多个源对象的所有 可枚举的自有键, 然后把它们赋值到(使用=)目标对象, 最后返回目标对象
为什么我们说
Object.assign()其实是一个浅复制, 来看一组代码
let myJSON = {
name: {
Tom: [{ 1: 1 }, { 2: 2 }],
},
age: [{ 3: 3 }, { 4: 4 }],
};
let b = {};
Object.assign(b, myJSON);
b.name.Tom.length = 1; // 此时的 myJSON.name.Tom 也会被影响, 因为是浅复制
delete b.age; // 此时 myJSON.age 还会存在, 因为 b 和 myJSON 是两个不同的对象
console.log(b); // { name: { Tom: [ {1:1} ] } }
console.log(myJSON); // { name: { Tom: [ [{1:1}] ] }, age: [ { 3: 3 }, { 4: 4 } ] }
b和myJSON是指向两个不同的object的指针, 但是他们里面的复杂对象(objectorarray), 这里是name,age则还是指向的同一个指针, 所以改变一个另一个也会跟这变. 但是,如果我们只改变最外层则不会受到影响, 因为b和myJSON还是两个不同的对象
2. 属性描述符
属性描述符是用来表示该对象内的属性的'配置'
Object.defineProperty( myObject, "a", {
value: 2,
writable: true,
configurable: true,
enumerable: true
}
);
value是属性a对应的值writable表示该属性是否可以修改(相当于是否有 setter)configurable表示该属性的属性描述符是否可以配置, 相当于 是否可以用defineProperty()来修改属性描述符, 同时如果configurable=flse, 该属性不能用delete删除
这里提一个面试的问题:
obj.a = null和delete obj.a有什么区别???
答: 当
configurable为flase的时候如果delete语句, 那么还是不会删除,还依旧存在, 不会被垃圾回收. 但是, 如果是obj.a =null如果writable为true. 那么, 可以是被垃圾回收的
enumerable表示该属性是否是可枚举(在for...in...,for...of...的时候是否会被遍历到)
3. 属性不变性
- 对象常量: 结合
writable:false和configurable:false可以创建一个真正的常量属性, 不能修改,重定义,删除 - 禁止扩展:
Object.preventExtensions(obj), 当使用这个方法之后, 我们往 obj 里面添加属性, 也不会生效Object.seal(obj)会对obj 中的所有的现有对象调用Object.preventExtensions(..), 所以在 seal() 之后不仅不能添加新属性, 也不能重新改写属性配置或者删除任何现有属性, 但是 如果writable = true则还能修改该属性值Object.freeze(obj), 会创建一个冻结对象, 想当于调用了Object.seal(obj)并且, 属性的writable = false;
举例:
var myObjcet = {
a:2
};
Object.preventExtensions(myObject);
myObject.b =3;
myObject.b // undefined;
4. Object.hasOwnProperty()
- 用来确定某个属性是否在该对象中, 不会检查
[[Prototype]]链
5. in
in操作符会在可以通过对象访问指定属性时返回true, 无论该属性是在实例上还实在其原型链中- 属性在枚举顺序上不定
- 在数组中
[1,3,5,6], 遍历的是0,1,2
是在原型上
6. Object.keys()
- 只返回该实例对象上的 key, 而不会去找 原型对象 上的 key
- 返回的枚举顺序不定