[TOC] ## 对象操作 ### delete obj.属性 删除key值 ``` var obj = { key1: 1, key2: 2 }; Object.keys(obj); // ['key1', 'key2'] delete obj.key1 console.log(Object.keys(obj)); //[ 'key' ] ``` ### Object.create() 对象的继承 ``` var a ={ name:"ad" }; var b=Object.create(a) b.name//ad ``` ### ... in obj 属性是否存在 ``` var a = {boo1:"boo11",boo2:"boo22"}; console.log("boo1" in a); //true console.log("toString" in a); //true ``` ### Obj.hasOwnProperty 判断是否是 此对象自身的属性 ``` Object.prototype.boo3 = "boo33" const Obj = {boo1:"boo11",boo2:"boo22"}; console.log('boo3' in Obj); //true console.log(Obj.hasOwnProperty("toString" )); //flase console.log(Obj.hasOwnProperty("boo1")); //true console.log(Obj.hasOwnProperty("boo3")); //false ``` ### for .. in 遍历可遍历的属性 遍历所有可遍历的属性(包括继承的) ``` for (var p in obj) { console.log(p); } ``` 遍历自身所有可遍历的属性 ``` for (var key in person) { if (person.hasOwnProperty(key)) { console.log(key); } } ``` ### set/get的用法 ``` var obj = Object.defineProperty({}, 'p', { get: function () { return 'getter'; }, set: function (value) { console.log('setter: ' + value); } }); //等价写法(推荐) var obj = { _a:"aa", get p(){ return this.a; }, set p(v){ console.log(v + "asd"); } }; ``` ### Object.getOwnPropertyDescriptor() 可获取属性的描述 ``` var obj = { p: 'a' }; Object.getOwnPropertyDescriptor(obj, 'p') // Object { value: "a", // writable: true, // enumerable: true, // configurable: true // } ``` 不能用于继承的属性 ``` var obj = { p: 'a' }; Object.getOwnPropertyDescriptor(obj, 'toString') // undefined ``` ### Object.getOwnPropertyNames() 返回对象自身的属性名(包括不可遍历) 返回一个数组,成员是参数对象本身的所有属性的键名,不包含继承的属性键名 ``` Object.getOwnPropertyNames(Math) [ 'abs', 'acos', 'acosh', ... ]; ``` ### Object.Key() 返回可遍历属性 ``` var a={} a.name=12; a.age=13; Object.keys(a));//[ 'name', 'age' ] ``` ### Object.defineProperty() 定义或者修改属性的描述 ``` var a ={name:"asd"} var obj = Object.defineProperty(Object,'age',{ value:"123", writable:false, enumerable:true, configurable:false, }) obj.age //123 obj.age="1233" //在严格模式下报错 obj.age =123 ``` #### 属性描述对象 对象的属性有几个描述性元素 - `value` 该属性的属性值 默认为 `undefined` - `writable` 表示属性值(`value`)是否可改变(即是否可写),默认为`true` - `enumerable` 是否可以遍历,默认`true` - `configurable` 默认为true。如果设为false,将阻止某些操作改写该属性,比如无法删除该属性(value属性除外)。也就是说,configurable属性控制了属性描述对象的可写性 - `get` 一个函数,表示该属性的取值函数(getter),默认为undefined - `set` 一个函数,表示该属性的存值函数(setter),默认为undefined ### Object.defineProperties defineProperty 可操作多个属性 ``` var obj = Object.defineProperties({}, { p1: { value: 123, enumerable: true }, p2: { value: 'abc', enumerable: true }, p3: { get: function () { return this.p1 + this.p2 }, enumerable:true, configurable:true } }); obj.p1 // 123 obj.p2 // "abc" obj.p3 // "123abc" ``` #### 技巧 json .stringify() 会排除`enumerable`为`false`的属性 ``` var a ={ name:"ad", age:123 }; Object.defineProperty(a,'name',{ enumerable:false, }); console.log(JSON.stringify(a));//{"age":123} ``` ### Object.preventExtensions() 使对象无法获取新的属性 ### Object.isExtensible() 判断是否可扩展 ``` var obj =new Object(); Object.preventExtensions(obj); obj.p=1;//TOypeError: Cannot add property p, object is not extensible Object.defineProperty(obj,'p',{ //报同上的错误 value:1 }); Object.isExtensible(obj) /false ``` > 可删除已有属性 ### Object.seal() 不可添加,也不可删除属性 ``` var obj =new Object(); obj.p=1 Object.seal(obj) obj.a=1 //TypeError: Cannot add property a, object is not extensible delete obj.p //TypeError: Cannot delete property 'p' of #<Object> ``` > `Object.seal`实质是把属性描述对象的configurable属性设为false,因此属性描述对象不再能改变了 > `Object.seal`只是禁止新增或删除属性,并不影响修改某个属性的值 ### Object.isSealed(obj) 判断是否使用了seal > 如果使用了 `seald` `Object.isExtensible(obj)` 也是返回false ### Object.freeze(obj) 无法增删改属性 ### Object.isFrozen() 检查是否`freeze` ### Object.getPrototypeOf() 返回参数对象的原型 ``` var F = function () {}; var f = new F(); Object.getPrototypeOf(f) === F.prototype // true ``` ### Object.setPrototypeOf() a对象共享b对象 ``` var a={} a.name="asd" var b={} b.age=12 Object.setPrototypeOf(a,b) a.age;//12 ``` ### Object.create() 从一个实例对象生成实例对象 ``` // 原型对象 var A = { print: function () { console.log('hello'); } }; // 实例对象 var B = Object.create(A); Object.getPrototypeOf(B) === A // true B.print() // hello B.print === A.print // true ``` `Object.create`方法还可以接受第二个参数 ``` var obj = Object.create({}, { p1: { value: 123, enumerable: true, configurable: true, writable: true, }, p2: { value: 'abc', enumerable: true, configurable: true, writable: true, } }); // 等同于 var obj = Object.create({}); obj.p1 = 123; obj.p2 = 'abc'; ``` ### Object.prototype.isPrototypeOf() ``` var o1 = {}; var o2 = Object.create(o1); var o3 = Object.create(o2); o2.isPrototypeOf(o3) // true o1.isPrototypeOf(o3) // true ``` o1和o2都是o3的原型。这表明只要实例对象处在参数对象的原型链上,isPrototypeOf方法都返回true ### `Object.prototype.__proto__` 不推荐 ``` var obj = new Object(); obj.__proto__ === Object.prototype // true obj.__proto__ === obj.constructor.prototype // true ``` ### with 关键词 在严格模式下不能使用 `wth`关键词 ``` var a = { name: 'hello', age: 'word' } with (a){ console.log(name); //hello console.log(age); //wird } ```