您当前的位置: 首页 > 

【03】

暂无认证

  • 1浏览

    0关注

    196博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Object原型、create、assign、get set属性拷贝

【03】 发布时间:2021-02-05 09:23:55 ,浏览量:1

NO.1 求证{}等同于new Object()
let obj = {}
// 等同于
let obj = new Object()

求证

let obj = {
    url: 'web03.cn'
}
obj.__proto__.name = '零三'
console.log(obj)
console.log({})
let obj1 = new Object()
console.log(obj1)

以上已经求证了{}等同于new Object() 以下反过来求证new Object()等同于{}

Object.prototype.name = '零三'
let obj = {
    url: 'web03.cn'
}
console.log(obj)
console.log({})
let obj1 = new Object()
console.log(obj1)

结果都为

NO.2 Object.assign会改变目标数组
let obj1 = {
    a:1,
    b:2
}
let obj2 = {
    a: 2,
    x:3,
    y:4
}
let obj3 = {
    m:5,
    n:6
}
let obj4 = Object.assign(obj1,obj2,obj3)
console.log('obj1=',obj1)
console.log('obj2=',obj2)
console.log('obj3=',obj3)
console.log('obj4=',obj4)

NO.3 Object.create()

new Object() 通过构造函数来创建对象, 添加的属性是在自身实例下。

Object.create() es6创建对象的另一种方式,可以理解为继承一个对象, 添加的属性是在原型下。

Object.prototype.name = '零三'
let obj = Object.create(null)
let obj1 = Object.create({url: 'web03.cn'})
console.log(obj)
console.log(obj1)
console.log(obj1.url)

Object.create() 方法创建的对象时,属性是在原型下面的

此时这个值不是obj自身的,是它通过原型链proto来访问到url的值。

创建对象属性的性质不同

// 创建一个以另一个空对象为原型,且拥有一个属性p的对象
let obj = Object.create({}, {url:{value: 'web03.cn'}})
// 省略了的属性特性默认为false,所以属性url是不可写,不可枚举,不可配置的
obj.url = 'https://web03.cn'
console.log(obj.url)//web03.cn
obj.name = '零三'
console.log(obj.name)//零三
for (let key in obj) {
	console.log(obj[key])//url不可枚举不能输出,结果只输出name的值
}
let isDel = delete obj.url
console.log(isDel)//false
console.log(obj)

Object.create() 用第二个参数来创建非空对象的属性描述符默认是为false的,而构造函数或字面量方法创建的对象属性的描述符默认为true

类似于

//创建一个构造函数或者类
let People = function(){}
People.prototype.url = 'web03.cn'
People.prototype.printUrl = function() {}
//通过构造函数创建实例
let p = new People();
console.log(p.__proto__ === People.prototype) // true
NO.4 Object.getPrototypeOf()

Object.getPrototypeOf用于读取一个对象的原型对象

Object.getPrototypeOf('foo') === String.prototype // true
Object.getPrototypeOf(true) === Boolean.prototype // true
NO.5 Object.assign()

Object.assign会改变原有的目标对象

let obj1 = {
    a:1,
    b:2
}
let obj2 = {
    a: 2,
    x:3,
    y:4
}
let obj3 = {
    m:5,
    n:6
}
let obj4 = Object.assign(obj1,obj2,obj3)
console.log('obj1=',obj1)
console.log('obj2=',obj2)
console.log('obj3=',obj3)
console.log('obj4=',obj4)

Object.assign不能合并不能被枚举的对象

let obj = {
    name: '零三',
    url: 'web03.cn'
};
Object.defineProperty(obj,'name', {
    enumerable: false, // 设为可枚举,不然 Object.assign 方法会过滤该属性
    get(){
        console.log('不会输出')
        return this.name
    }
});

let obj1 = Object.assign(Object.create(Object.getPrototypeOf(obj)), obj)
console.log(obj1)

Object.assign() 方法不能正确拷贝 get ,set 属性

let obj = {
    name: '零三',
    url: 'web03.cn'
};


function setName() {
    this.name = '零零三';
}
Object.assign(setName.prototype, obj)
let result = new setName()
console.log(result)

Object.defineProperty(result,'getName', {
    enumerable: true,
    get(){
        return "我是:" + this.name
    }
});

let result2 = Object.assign(Object.create(Object.getPrototypeOf(obj)), obj)
console.log(result2)

原型属性的继承 拷贝一个构造函数的实例

// 继承
let obj = {
    name: '零三'
};
function setName() {
    this.name = '零零三';
}

// console.log(setName.prototype = obj)
// console.log(setName.prototype.constructor === setName)//false
Object.assign(setName.prototype, obj)
console.log(setName.prototype.constructor === setName)
let result = new setName();
console.log(result)
console.log(result.name)
console.log(result.__proto__.name)

不能拷贝到继承或原型上的方法的

let obj = {
    name: '零三',
    url: 'web03.cn'
};
function setName() {
    this.name = '零零三';
}
Object.assign(setName.prototype, obj)
let result = new setName();
console.log(result)
let result2 = Object.assign({},result)
console.log(result2)

因为 Object.assing 是不能拷贝到继承或原型上的方法的。所以 实例result2 没有 result原型上的内容

实现原型属性的拷贝
let obj = {
    name: '零三',
    url: 'web03.cn'
};
function setName() {
    this.name = '零零三';
}
Object.assign(setName.prototype, obj)
let result = new setName();
console.log(result)
let result2 = Object.create(Object.getPrototypeOf(result), Object.getOwnPropertyDescriptors(result));
console.log(result2);

可以把Object.create()的参数理解为:第一个参数是放在新对象的原型上的,第二个参数是放在新对象的实例上的。

所以 Object.getPrototypeOf() 得到的是 result 对象的原型,然后作为第一个参数,所以会在新对象result2 的原型上。

Object.getOwnPropertyDescriptors() 得到是 result 对象自身的可枚举属性,作为第二个参数,放在 result2 的实例上。因为Object.assign() 方法不能正确拷贝 get ,set 属性(上面有提到)

实现get 、set 属性的正确拷贝
let obj = {
    name: '零三',
    url: 'web03.cn'
}
let obj2 = {
    __proto__: obj,
    age: 18,
    getAge() {
        return this.age
    },
    get getAge2() {
        return this.age
    }
};
Object.defineProperty(obj2,'getName', {
    enumerable: true,
    get(){
        return "我是:" + this.name
    }
});
let result = Object.create(obj, Object.getOwnPropertyDescriptors(obj2))
console.log(result)

关注
打赏
1657344724
查看更多评论
立即登录/注册

微信扫码登录

0.1003s