[toc]
Analysis: What does New do
The new operator generates an instance object by executing either a custom constructor or a built-in JS constructor.
In MDN, the internal operation is roughly divided into four steps:
- Create an empty simple JavaScript object (that is {});
- Link this object (that is, set its constructor) to another object;
- Use the new object created in Step 1 as the context for this;
- If the function does not return an object, this is returned.
Walk through the above steps with a simple demo
function Person (name){
this.name = name
}
let p = new Person('jack');
console.log(`p:`, p); // { name: 'jack' }
console.log(`p.__proto__===Person.prototype:`,p.__proto__===Person.prototype); //true
Copy the code
You can see that after executing the Person constructor, the new operator returns a new object created internally, executes the Person function on that object as the context for the post, and returns it, with the prototype property of object P pointing to the prototype of the constructor. This ensures that the instance can access the properties and methods defined in the constructor prototype.
In the demo above, constructors do not return values. What if constructors return values
function Person (name){
this.name = name;
return {age: 18}}let p = new Person('jack');
console.log(`p:`, p); // { age: 18 }
Copy the code
If the constructor returns an object at the end, it returns it directly, rather than creating a new object internally.
After tests found, in addition to return objects, if return to the other types, as long as the return type is a reference type object or function (function, object, Array, the Date, the Error, the Regexp, to exclude null, Because typeof NULL === ‘object’) returns it directly, and all other primitive types return internally newly created objects.
Custom implementation
Here we try to mimic the main function of the new operator by encapsulating a myNew method: it takes several arguments, the first of which is the constructor CTR, and the rest are the arguments required by the constructor, myNew(CTR, arg1, arg2…).
The first step
The first step here puts together steps 1 and 2 in MDN: create a new object and point its __proto__ attribute to the constructor’s Prototype attribute
function myNew(ctr) {
let obj = Object.create(ctr.prototype);
}
Copy the code
You can also use the following methods
function myNew (ctr){
let obj = {};
obj.__proto__ = ctr.prototype;
}
Copy the code
The second step
After the parameters are obtained, the constructor is executed to assign a value to the newly created object obj as the thread
function myNew(ctr) {
let obj = Object.create(ctr.prototype);
const args = [].slice.call(arguments.1);
let result = ctr.apply(obj, args);
console.log(`obj:`,obj);
}
Copy the code
Const args = [].slice.call(arguments, 1); Use array.form (arguments).slice(1) or […arguments].slice(1).
The third step
The constructor returns the value result. If the constructor eventually returns other reference types such as object, function, array, date, and Symbol, they are returned directly. The other primitive types, null, and undefined, return the internally created instance of the object.
function myNew(ctr) {
let obj = Object.create(ctr.prototype);
const args = [].slice.call(arguments.1);
let result = ctr.apply(obj, args);
var isObj = (typeof result === 'object'&& result ! = =null);
var isFn = typeof result === 'function';
return (isObj || isFn) ? result : obj;
}
Copy the code
test
Finally, simply test that there is no return value
function Person(name) {
this.name = name;
}
let p = myNew(Person,'jack');
console.log(`p:`,p);
Copy the code
Returns a value
function Person(name) {
this.name = name;
return {age: 33}}let p = myNew(Person,'jack');
console.log(`p:`,p);
Copy the code
reference
Can you manually implement a new operator understanding that mimics implementing JS’s new operator