• Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.

To understand the

The object.create () method creates a new Object, using an existing Object to provide the __proto__ of the newly created Object.

const person = { isHuman: false, printIntroduction: function() { console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`); }}; const me = Object.create(person); me.name = 'Matthew'; // "name" is a property set on "me", but not on "person" me.isHuman = true; // inherited properties can be overwritten me.printIntroduction(); // expected output: "My name is Matthew. Am I human? true"Copy the code

parameter

proto

The prototype object of the newly created object.

propertiesObject

Optional. You need to pass in an Object whose property type refers to the second parameter of Object.defineProperties(). If this parameter is specified and not undefined, the incoming object’s own enumerable properties (that is, properties defined by itself, rather than enumerated properties in its stereotype chain) will add the specified property value and corresponding property descriptor to the newly created object.

Handwritten implementation

Determine the parameters of the function, and error handling. Keep it consistent with native apis

function newCreate(proto, propertiesObject) { if (typeof proto ! == 'object' && typeof proto ! == 'function') { throw TypeError('Object prototype may only be an Object: ' + proto) } }Copy the code

Next, we know that the prototype of the Object created by Object.create is actually proto

So our object’s __proto__, that is, changes its constructor’s prototype

function F() { }
F.prototype = proto
const o = new F()
Copy the code

Finally we are working on the propertiesObject, adding descriptors to our properties

if (propertiesObject ! == undefined) { Object.keys(propertiesObject).forEach(prop => { let desc = propertiesObject[prop] if (typeof desc ! == 'object' || desc === null) { throw TypeError('Object prorotype may only be an Object: ' + desc) } else { Object.defineProperty(o, prop, desc) } }) }Copy the code

The complete code

function newCreate(proto, propertiesObject) { if (typeof proto ! == 'object' && typeof proto ! == 'function') { throw TypeError('Object prototype may only be an Object: ' + proto) } function F() { } F.prototype = proto const o = new F() if (propertiesObject ! == undefined) { Object.keys(propertiesObject).forEach(prop => { let desc = propertiesObject[prop] if (typeof desc ! == 'object' || desc === null) { throw TypeError('Object prorotype may only be an Object: ' + desc) } else { Object.defineProperty(o, prop, desc) } }) } return o }Copy the code

test

We used JEST for our unit tests

So let’s first introduce the function that we just wrote

const newCreate = require('.. /index') Object.prototype.newCreate = newCreateCopy the code

Situation (1)

When there is only one parameter

Describe ('Object create implementation ', () => {it(' only one argument ', () => {const person = {age: '18', say: function(){ return `I am ${this.name}, I am ${this.age} years old` } } const newCreate = Object.newCreate(person) const originCreate = Object.create(person) newCreate.name = 'Tom' originCreate.name = 'Tom' expect(newCreate.say()).toBe(originCreate.say()) }) })Copy the code

The test pass

Situation 2.

When we have an argument, add a descriptor to our property

It (' there is a second argument ', () => {const target = {a: 1} let cVal = 3 const properies = {b: {value: 2}, c: {get: function(){ return cVal }, set: function(val){ cVal = val } } } const newCreate = Object.newCreate(target, properies) expect(newCreate.b).toBe(2) expect(newCreate.c).toBe(3) newCreate.c = 4 expect(newCreate.c).toBe(4) })Copy the code

Situation 3.

There is a second argument, but the argument is not a wrapper object

It (' second argument, but not wrapper object ', () => {const properies = {c: null } expect(() => Object.newCreate({}, properies)).toThrow(TypeError) })Copy the code

Situation (4)

Parameters of the abnormal

It (' parameters of abnormal, () = > {expect (() = > Object. NewCreate ()), toThrow (TypeError) expect (() = > Object.newCreate(undefined)).toThrow(TypeError) expect(() => Object.newCreate(true)).toThrow(TypeError) })Copy the code

All tests passed.