JS手撕(五) new、Object.create()、Object.assign()
new关键字
实现new
关键字,首先得了解一下new
关键字究竟干了什么。
new
关键字主要干了四件事:
创建一个新对象
设置该对象的原型为构造函数的原型(保留原有原型链)
执行构造函数,this
指向新对象
如果构造函数返回值是对象,返回该对象。否则,返回1
创建的对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| function myNew(Func, ...args) { const obj = Object.create(null);
Object.setPrototypeOf(obj, Func.prototype);
const result = Func.apply(obj, args);
return (typeof result === 'object' && result !== null) ? result : obj; }
|
因为Object.create()
可以使用现有的对象来作为新建对象的原型,所以第1
、2
步是可以合在一起的。
即:
1
| const obj = Object.create(Func.prototype);
|
测试:
1 2 3 4 5 6 7 8 9
| function Person(name, age) { this.name = name; this.age = age;
}
const person = myNew(Person, 'clz', 21); console.log(person);
|
Object.create()
Object.create()
方法用于创建一个新对象,使用现有的对象来作为新建对象的原型。
实现一个低配版的,不考虑第二个参数。
核心就是一种实现继承的方法。(道格拉斯·克罗克福德在一篇文章中介绍的一种实现继承的方法)
1 2 3 4 5
| function object(o) { function F() {} F.prototype = o; return new F(); }
|
完整代码:
1 2 3 4 5 6 7 8 9 10 11
| function object(o) { function F() { } F.prototype = o; return new F(); }
Object.myCreate = function (proto) { const obj = object(proto); return obj; }
|
测试:
1 2 3 4 5 6 7
| function Animal(type) { this.type = type; }
const pig = Object.myCreate(Animal); pig.type = 'pig'; console.log(pig);
|
还有一个问题:我们有时候会使用Object.create(null)
创建一个没有原型的对象,但是现在是有问题的。
1 2
| const obj = Object.myCreate(null); console.log(obj);
|
所以还需要判断参数是null
的时候,设置原型为null
来实现能够创建一个没有原型的对象。
1 2 3 4 5 6 7 8 9
| Object.myCreate = function (proto) { const obj = object(proto);
if (proto === null) { Object.setPrototypeOf(obj, null); }
return obj; }
|
Object.assign()
Object.assign()
将所有可枚举并且是自身属性从一个或多个源对象复制到目标对象,返回修改后的对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| Object.myAssign = function (target, ...sources) { sources.forEach(source => { for (const key in source) {
if (source.hasOwnProperty(key)) { target[key] = source[key]; } } })
return target; }
|
测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| const target = { name: 'clz' };
const source1 = { name: '赤蓝紫' }; const source2 = { age: 21 }; const source3 = { age: 999 };
const result = Object.myAssign(target, source1, source2, source3); console.log(result); console.log(target === result);
|
参考
GitHub - qianlongo/fe-handwriting: 手写各种js Promise、apply、call、bind、new、deepClone….
JavaScript之手撕new_战场小包的博客-CSDN博客