如果你自以为会对象深拷贝的话,快来看看这篇对象进阶的文章吧~~~
1.创建对象
-
对象创建的三种方式
- var obj = new Object();
- var obj = {};
- var obj = Object.create();
- var obj1 = Object.create(obj);
把obj作为原型,创建obj1对象,obj上面有什么内容,obj1就有
var obj = {a : 1}; var obj1 = Object.create(obj); var obj2 = Object.create(obj1); obj1.a = 10; obj2.a = 100; console.log(obj.a, obj1.a, obj2.a);//1 10 100 console.log(obj, obj1, obj2);
-
对比两种创建方式
如果对象没有对象属性,则获取离他最近的一层的原型链属性;
如果有对象属性.直接返回对象属性
应当直接设置对象属性(实例属性),不能直接设置原型链属性
var obj = {a : 1}; var obj1 = Object.create(obj); obj.a = 10; console.log(obj1.a); //10 console.log(obj === obj1.__proto__);//true
-
__proto__
var arr = [1, 2, 3, 4]; console.log(arr.__proto__); arr.__proto__.slice1 = function () { console.log("aaa"); } var arr1 = [4, 5, 6]; console.log(arr1.__proto__); //在arr的原型上添加了slice方法,arr1也能访问到
2.复制对象
-
Object.assign
用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
第一个参数是要复制到的目标对象,后面参数均为源对象
-
同名属性的替换
const target = { a: { b: 'c', d: 'e' } } const source = { a: { b: 'hello' } } Object.assign(target, source); // { a: { b: 'hello' } }
-
只能浅复制,属性的引用对象会仍旧是引用关系
var obj3 = {}; var obj4 = obj3; obj3 = Object.assign(obj3, obj); console.log(obj3 === obj4); //true
-
不可枚举属性不能复制
var obj = {a : 1}; var obj1 = Object.create(obj); obj1.a = 100; console.log(obj1); var obj2 = Object.assign({}, obj); console.log(obj2);
-
浅拷贝对象
- 遍历所有的内容
for (var prop in obj) {
}
可以复制多个
Object.assign({}, obj);只能复制一个(没有引用关系)
var obj1 = JSON.parse(JSON.stringify(obj));-
覆盖原对象的引用地址
var obj3 = { e: 20 };
var obj4 = obj3;
obj3 = { ...obj };
console.log(obj3 === obj4); //false
- 遍历所有的内容
3.定义属性和获取属性
-
Object.defineProperty
在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。
var obj = {}; Object.defineProperty(obj,"a",{ configurable:false, //不可删除,不可修改描述对象 writable:false, //只读,不可修改 enumerable:false,//设置为不可枚举,不能用for in枚举,但可以继承 value:10 })
- 如果没有设置configurable,enumerable,writeable时,默认为false
var obj = {}; Object.defineProperty( obj , "a" , { value:20; } for (var attr in obj) { console.log(attr); } // 属性 a 不可枚举 ; 不能被for in 循环遍历出来; obj.a = 10; // 属性 a 只读 ; 不能被赋值 (赋值无效); delete obj.a; // 属性 a 不可被删除 ;
- 当设置set || get时,不能定义value和writable属性
var obj = {}; Object.defineProperty(obj,"b",{ configurable : false, enumerable : false, set : function(value){ this._a = value; }, get:function(){ return this._a; } })
- 向对象中添加length属性
var obj = { a : 1, b : 2, c : 3, d : 4 } Object.defineProperty(obj,"length",{ get : function(){ var length = 0; for(var attr in this){ length ++; } // console.log(this);// 指向当前的对象; return length ; }, set : function(val){ // console.log("这是set拦截器打印的内容",val); if(val === 0){ for(var attr in this){ delete this[attr]; } } } }) console.log(obj.length); //4
-
Object.getOwnPropertyNames
返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组
var obj = {}; Object.defineProperties(obj, { a: { enumerable: false, value: 10, configurable: true, writable: true }, b: { configurable: true, value: 100 } }) var names = Object.getOwnPropertyNames(obj); console.log(names);// ["a", "b"] for (var i = 0; i < names.length; i++) { console.log(names[i],obj[names[i]]); } // a 10 // b 100
-
getOwnPropertyDescriptor遍历描述对象
返回指定对象上一个自有属性对应的属性描述
(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性)
var obj = {}; Object.defineProperties(obj, { a: { enumerable: false, value: 10, configurable: true, writable: true }, b: { configurable: true, value: 100 } }) for (var i = 0; i < names.length; i++) { console.log(Object.getOwnPropertyDescriptor(obj,names[i])); } //{value: 10, writable: true, enumerable: false, configurable: true} //{value: 100, writable: false, enumerable: false, configurable: true}
4.对象深复制
-
版本1
class Box { static ARG = ["a", "b"]; constructor(a, b) { this.a = a; this.b = b; } play() { console.log(this.a + this.b); } } var obj = { a: 1, b: "a", c: false, d: { e: undefined, f: null, g: [1, 2, 3, 4, 5], h: new Date(), i: /^[a-z]{2,4}$/gi, j: new Box(4, 5), k: { } } } Object.defineProperties(obj.d.k, { l: { value: 10 }, m: { configurable: true, writable: true, value: 20 }, n: { enumerable: true, value: function () { console.log("aaaa"); } }, o: { value: new Image() } }) function cloneObject(target, source) { var names = Object.getOwnPropertyNames(source); for (let i = 0; i < names.length; i++) { var desc = Object.getOwnPropertyDescriptor(source, names[i]); if (typeof desc.value === "object" && desc.value !== null) { var obj; if (desc.value instanceof HTMLElement) { obj = document.createElement(desc.value.nodeName); } else { switch (desc.value.constructor) { case Box: obj = new desc.value.constructor(desc.value[Box.ARG[0]], desc.value[Box.ARG[1]]); break; case RegExp: obj = new desc.value.constructor(desc.value.source, desc.value.flags); break; default: obj = new desc.value.constructor(); } } cloneObject(obj, desc.value); Object.defineProperty(target, names[i], { value: obj, enumerable: desc.enumerable, writable: desc.writable, configurable: desc.configurable }) } else { Object.defineProperty(target, names[i], desc); } } return target; } var obj1 = cloneObject({}, obj); obj.d.k.m = 100; console.log(obj1);
<u>版本二(由于篇幅过长,后续介绍)</u>
5.对象方法
-
freeze()
冻结一个对象。
一个被冻结的对象再也不能被修改;
冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。
此外,冻结一个对象后该对象的原型也不能被修改。
const obj={a:1,b:2}; //适用于做配置静态属性
Object.freeze(obj);
const obj = { a: 1, b: 2 }; Object.freeze(obj); obj.a = 2; //debugger; 断点 delete obj.a; console.log(obj); //{a: 1, b: 2}
-
in判断是否为对象属性或者原型属性
var obj = { a: 1, b: 2 }; Object.defineProperty(obj, "c", { value: 10 }) var obj1 = Object.create(obj); console.log("c" in obj1);//true
-
hasOwnProperty判断是否为对象属性,不能判断原型属性
var obj = { a: 1, b: 2 }; var obj1 = Object.create(obj); console.log(obj.hasOwnProperty("a"));//true console.log(obj1.hasOwnProperty("a"));//false
-
isPrototypeOf 判断obj是否为obj1的原型链
var obj = { a: 1, b: 2 }; var obj1 = Object.create(obj); console.log(obj.isPrototypeOf(obj1));//true
-
typeof返回操作数的类型
number string boolean undefined object function symbol
console.log(typeof 42); // "number" console.log(typeof 'blubber');// "string" console.log(typeof true); // "boolean"
-
instanceof 判断该对象的原型链上是否有这个类型
var arr = [1, 2, 3]; class Box extends Array { constructor() { super(); } } let b = new Box(); console.log(arr instanceof Array);//true console.log(arr instanceof Object);//true console.log(b instanceof Object);//true console.log(b instanceof Array);//true console.log(b instanceof Box);//true
-
constructor 判断该对象的抽象类
class Box extends Array { constructor() { super(); } } let b = new Box(); console.log(b.constructor===Box);//true
-
propertyIsEnumerable 判断对象下某个属性是否可以枚举
var obj = { a: 1, b: 2 }; Object.defineProperty(obj, "c", { value: 10 }) var obj1 = Object.create(obj); console.log(obj.propertyIsEnumerable("b"));//true console.log(obj1.propertyIsEnumerable("b"));//false
6.预习案例
使以下语句为true
(obj.a === 1 && obj.a === 2 && obj.a === 3)
- 方法一
var n = 1;
var obj = {
a:n;
}
Object.defineProperty(obj, "a", {
get: function() {
return n++;
}
})
console.log(obj.a === 1 && obj.a === 2 && obj.a === 3);
- 方法二
{
$data: {
a: 1
}
}
Object.defineProperty(obj, "a", {
get: function () {
return this.$data.a++;
}
})
console.log(obj.a === 1 && obj.a === 2 && obj.a === 3);