# Object
# Object.create
Object.create 创建一个对象并把这个对象的 [[Prototype]] 关联到指定的对象。
Object.create(proto, [propertiesObject])
- proto : 必须。表示新建对象的原型对象,该参数可以是null, 对象, 函数的prototype属性 (创建空的对象时需传null , 否则会抛出TypeError异常)。
- propertiesObject : 添加到新创建对象的可枚举属性。
let a = Object.create({name:'kira',info:{value:'111'}})
console.log(a) // {}
console.log(a.__proto__) //打印结果{name:'kira'},info:{value:'111'}}
console.log(a.__proto__.__proto__) //打印结果是Object的内容
//利用Object.create的第二个参数,给创建的新对象增加属性
let obj = {name:1}
//新增加的属性必须有enumerable属性,不然在新创建的对象上找不到。
let c = Object.create(obj,{age: { value: 24,enumerable: true,}})
console.log(c) // {age:24}
console.log(c.__proto__) // {name:1}
console.log(c.__proto__.__proto__) // {name:1}
# Object.create 和 {} 区别
- Object.create自定义自己的原型
- Object.create(null); //{} 没有原型
let a = {}
console.log(a);// {}
consloe.log(a.__proto__)//打印的是Object的内容
var anotherObject = { a:2};
// 创建一个关联到 anotherObject 的对象
var myObject = Object.create( anotherObject );
myObject.a; // 2 实际上就是把a:2 挂载到了myObject上
# Object.create的简单实现
//方法1
Object.create1 = function (proto){
if (typeof proto !== "object" && typeof proto !== "function") {
// 类型校验
throw new TypeError("proto必须为对象或者函数");
} else if (proto === null) {
// null 特殊处理
throw new Error("不支持传递null");
}
let obj = {};
//IE下兼容性不好.__proto__不推荐
obj.__proto__ = proto
return obj;
}
//方法2
Object.create1 = function (proto){
if (typeof proto !== "object" && typeof proto !== "function") {
// 类型校验
throw new TypeError("proto必须为对象或者函数");
} else if (proto === null) {
// null 特殊处理
throw new Error("不支持传递null");
}
//构造函数
function F(){}
//更改prototype
F.prototype = proto;
//生成构造函数的实例
return new F();
}
# Object.create 一些问题
const fatherObj = {name:'father',age:20}
let obj = Object.create(fatherObj,{test:{value:1,enumerable:true,writable:true}})
console.log(obj)//{test:1}
console.log(obj.__proto__) //{ name: 'father', age: 20 }
obj.test++;
console.log(obj)//{test:2}
obj.age++;
console.log(obj)//test:2,age:21}
console.log(obj.__proto__) //{ name: 'father', age: 20 }
//fatherObj.age = 33;
console.log(obj)//test:2,age:21}
console.log(obj.__proto__) //{ name: 'father', age: 33 }
# Object.assign 的用法
Object.assign 可以实现对象的合并。Object.assign(target, ...sources)
# 同名属性 source 替换 targe 属性
Object.assign()方法只会合并替换对象的第一层 key,对于多层的,会当做值处理。(即 Object.assign 是浅拷贝的合并)
Object.assign 会将 source 里面的可枚举属性复制到 target。如果和 target 的已有属性重名,则会覆盖。同时后续的 source 会覆盖前面的 source 的同名属性。
let obj1 = {
a: {
b: {
c: "111"
}
}
};
let obj2 = {
a: {
b: {
d: "222"
}
}
};
Object.assign(obj1, obj2);
//输出结果
a: {
b: {
d: "222"
}
}
# object.assign 浅拷贝问题
Object.assign 只能拷贝第一层。
let a = {a:1,b:2}
let b= {c:3,d:{name:'kira'}};
let obj = Object.assign({},a,b);
console.log(obj);
//{ a: 1, b: 2, c: 3, d: { name: 'kira' } }
a.a = 66;
console.log(obj); //修改a发现obj并没有被改变。
// { a: 1, b: 2, c: 3, d: { name: 'kira' } }
b.d.name = 'test';
console.log(obj);//修改name时候,发现obj被改变了。
//{ a: 1, b: 2, c: 3, d: { name: 'test' } }
c
# 深拷贝实现 merge
let a = { a: {age:25}, b: 2, c: {}}
let b = { c: 3, a: { name: 'kira' },f: {} };
function mergeDeep(a,b) {
for (key in b) {
if (a[key] && a[key].toString() === '[object Object]' ) {
mergeDeep(a[key],b[key])
} else {
a[key] = b[key];
}
}
}
mergeDeep(a, b)
console.log('----a',a)
# 深比较判断两个对象是否相等
const a = {a:10,b:{c:10,d:20}}
const b = {a:10,b:{c:10,d:20}}
//
function isEqual(a,b) {
let result = true ;
for (let key in b){
if(a[key] === undefined){
result = false
}
if(typeof b[key] == 'object' && b[key]!==null){
const res = isEqual(a[key],b[key])
if(res === false) return false;
}else{
if (a[key] !== b[key]){
result = false
}
}
console.log('11',result)
}
return result;
}
# 什么是浅拷贝
新建一个对象,这个对象有原始对象属性值的一份精确拷贝。
浅拷贝只拷贝一层,如果属性是基本数据类型就拷贝值。如果属性是引用类型就拷贝地址。
let a = {name:'kira',info:{age:25}}
let b = Object.assign({},a)
a.name = '123'
a.info.age = 23
console.log(a) //{name:'123',info:{age:23}}
console.log(b)//{name:'kira',info:{age:23}}
# 两个对象之间的比较
let a = {a:1}
let b = {a:1}
let c = new Object(a)
console.log(a === b) // false 两个对象在堆中的指针地址不同
console.log(a === c) // true 两个对象的指针地址相同