- 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.