preface
Hi, I’m Wakawa. This is the first part of the interviewers’ questions series, which aims to help readers improve the basic knowledge of JS, including new, call, apply, this, inheritance related knowledge.
The interviewer asked the following article series: Interested readers can click here to read it.
Q: Can you simulate the JS new operator? Q: can you simulate the JS call and apply methods? Interviewer: JS inheritance
Those of you who have used Vuejs know that you need to instantiate with the new operator.
new Vue({
el: '#app',
mounted(){},
});
Copy the code
Then the interviewer may ask if they have thought about itnew
What did you do and how do you simulate it.
There are already many articles that simulate the new operator, so why write it again? Learning is like a mountain. People climb the mountain along different paths and share the scenery they see. You may not be able to see the scenery others see, feel the mood of others. Only oneself go climbing, can see different scenery, experience is more profound.
What does New do
Let’s start with simple example 1:
Function Student(){} var Student = new Student(); console.log(student); // {} // Student is an object. console.log(Object.prototype.toString.call(student)); // [object object] new object (); // By the way, 'new Object' (not recommended) and Object() also have the same effect. // You can guess that the internal judgment is made, using new call /** if (! (this instanceof Object)) { * return new Object(); * } */ var obj = new Object(); console.log(obj) // {} console.log(Object.prototype.toString.call(student)); // [object Object] typeof Student === 'function' // true typeof Object === 'function' // trueCopy the code
From this example, we can see that a function usesnew
Operator to generate a completely new object. andStudent
andObject
It’s all functions, it’s justStudent
It’s our custom,Object
isJS
It’s built-in. Take a look at the console output, interested readers can try on the console. 与new Object()
The generated objects are differentnew Student()
There is also a layer nested between the generated objects__proto__
, it’sconstructor
isStudent
This function.
// constructor === student; Student.prototype.constructor === Student;Copy the code
Summary 1: From this simple example,new
The operator does two things:
- A completely new object is created.
- This object will be executed
[[Prototype]]
(i.e.__proto__
Links).
Let’s take a look at the upgraded version of example 2:
Function Student(name){console.log(' before assignment -this', this); // {} this.name = name; Console. log(' after assignment -this', this); // {name: 'wakawa '}} var student = new student (' wakawa '); console.log(student); // {name: 'ruokawa '}Copy the code
We can see that this in the Student function refers to the object Student generated by new Student().
Summary 2: From this example,new
The operator does one more thing:
- The generated new object is bound to the function call
this
.
Let’s move on to the upgraded version of Example 3:
Function Student(name){this.name = name; // this.doSth(); } Student.prototype.doSth = function() { console.log(this.name); }; Var student1 = new Student(' if '); Var student2 = new Student(' student2 '); console.log(student1, student1.doSth()); // {name: 'if '}' if 'console.log(student2, student2.dosth ()); / / {name: 'sichuan'} 'sichuan' student1. __proto__ = = = Student. The prototype; // true student2.__proto__ === Student.prototype; // __proto__ is the browser implementation of the view prototype scheme. Object.getprototypeof (student1) === student.prototype; // true Object.getPrototypeOf(student2) === Student.prototype; // trueCopy the code
On the JS prototype relationship before the author saw this picture, feel very good, share to everyone.
Summary 3: This example 3 proves once againSummary 1In theThe second point. So this object is going to be executed[[Prototype]]
(i.e.__proto__
Links). And throughnew Student()
Each object created will eventually be[[Prototype]]
Link to thisStudent.protytype
On the object.
Careful students may notice that none of the functions in these three examples return a value. So what happens if you have a return value. So let’s look at example 4
Function Student(name){this.name = name; // Null (Null) // Undefined (Undefined) // Number (Number) 1 // String '1' // Boolean (Boolean) true // Symbol (Symbol) Function (){} // Array [] // Date() new Date() // RegExp (regular expression) /a/ // Error New Error() // return /a/; } var student = new student (' wakawa '); console.log(student); {name: 'wakawa '}Copy the code
After testing these seven types of MDN JavaScript types, I found that the first six basic types all return {name: ‘Ruokagu ‘}, and the following objects (including Functoin, Array, Date, RegExg, Error) all return these values directly.
Conclusion 4:
- If the function does not return an object type
Object
(including,Functoin
.Array
.Date
.RegExg
.Error
), thennew
The function call in the expression automatically returns the new object.
Combining these summaries, they add up to:
- A completely new object is created.
- This object will be executed
[[Prototype]]
(i.e.__proto__
Links). - The generated new object is bound to the function call
this
. - through
new
Each object created will eventually be[[Prototype]]
Link to this functionprototype
On the object. - If the function does not return an object type
Object
(including,Functoin
.Array
.Date
.RegExg
.Error
), thennew
The function call in the expression automatically returns the new object.
New Simulation implementation
Knowing these phenomena, we can simulate the implementation of the new operator. Post code and comments directly
/ simulation to realize the new operator * * * * @ param {Function} ctor/constructor * @ return {Object | Function | Regex | Date | Error} [return results] * / Function newOperator(ctor){ if(typeof ctor ! == 'function'){ throw 'newOperator function the first param must be a function'; } // ES6 new.target refers to the constructor newoperator. target = ctor; Create a new object, // 2. Execute the [[Prototype]] link // 4. Each object created with 'new' will eventually be linked to the function's 'Prototype' object by '[[Prototype]]'. var newObj = Object.create(ctor.prototype); ES6 [...arguments], Aarry. From (arguments); Var argsArr = [].slice.call(arguments, 1); var argsArr = [].slice.call(arguments, 1); // 3. The generated new object is bound to the function call 'this'. Var ctorReturnResult = ctor.apply(newObj, argsArr); Typeof NULL is also 'Object', so it is not equal to null. Null var isObject = typeof ctorReturnResult === 'object' && ctorReturnResult! == null; var isFunction = typeof ctorReturnResult === 'function'; if(isObject || isFunction){ return ctorReturnResult; } // 5. If the function does not return the Object type 'Object' (including 'Functoin', 'Array', 'Date', 'RegExg', 'Error'), then the function call in the 'new' expression automatically returns the new Object. return newObj; }Copy the code
Finally, verify example 3 with the simulated newOperator function:
Function Student(name, age){this.name = name; this.age = age; // this.doSth(); // return Error(); } Student.prototype.doSth = function() { console.log(this.name); }; Var student1 = newOperator(Student, 'if ', 18); Var student2 = newOperator(Student, student2, 18); // var student1 = new Student(' if '); // var student2 = new Student(' chuan '); console.log(student1, student1.doSth()); // {name: 'if '}' if 'console.log(student2, student2.dosth ()); / / {name: 'sichuan'} 'sichuan' student1. __proto__ = = = Student. The prototype; // true student2.__proto__ === Student.prototype; // __proto__ is the browser implementation of the view prototype scheme. Object.getprototypeof (student1) === student.prototype; // true Object.getPrototypeOf(student2) === Student.prototype; // trueCopy the code
As you can see, it fits well with the new operator. Readers are welcome to point out any shortcomings or improvements they find. If you look back at the simulated new operator implementation, the biggest credit belongs to the OBJECT.create () API provided by ES5.
Object.create() Example usage
As I mentioned in a previous article, you can look at all the API parsing of JavaScript objects
MDN Object.create()
The object.create (proto, [propertiesObject]) method creates a new Object, using an existing Object to provide the __proto__ of the newly created Object. It takes two arguments, but the second optional argument is the property descriptor (less commonly used; the default is undefined).
Var anotherObject = {name: 'ruokawa'}; Var myObject = object.create (anotherObject, {age: {value: 18,},}); GetPrototypeOf (anotherObject) === object.prototype; // getPrototypeOf(anotherObject) === object.prototype; // Prototype object.getPrototypeof (myObject); // {name: "Wakawa "} myObject.hasownProperty ('name'); // false; Note that name is on the prototype. myObject.hasOwnProperty('age'); // true indicates that age is its own myobject.name; // myobject.age; / / 18;Copy the code
For browsers that do not support ES5, the PloyFill scheme is provided on the MDN.
if (typeof Object.create ! == "function") { Object.create = function (proto, propertiesObject) { if (typeof proto ! == 'object' && typeof proto ! == 'function') { throw new TypeError('Object prototype may only be an Object: ' + proto); } else if (proto === null) { throw new Error("This browser's implementation of Object.create is a shim and doesn't support 'null' as the first argument."); } if (typeof propertiesObject ! = 'undefined') throw new Error("This browser's implementation of Object.create is a shim and doesn't support a second argument."); function F() {} F.prototype = proto; return new F(); }; }Copy the code
At this point, the article is basically finished. Thank you for reading this.
To sum up:
new
What was done:
- A completely new object is created.
- This object will be executed
[[Prototype]]
(i.e.__proto__
Links).- The generated new object is bound to the function call
this
.- through
new
Each object created will eventually be[[Prototype]]
Link to this functionprototype
On the object.- If the function does not return an object type
Object
(including,Functoin
.Array
.Date
.RegExg
.Error
), thennew
The function call in the expression automatically returns the new object.
- How to simulate it
Function newOperator(ctor){if(typeof ctor! == 'function'){ throw 'newOperator function the first param must be a function'; } newOperator.target = ctor; var newObj = Object.create(ctor.prototype); var argsArr = [].slice.call(arguments, 1); var ctorReturnResult = ctor.apply(newObj, argsArr); var isObject = typeof ctorReturnResult === 'object' && ctorReturnResult ! == null; var isFunction = typeof ctorReturnResult === 'function'; if(isObject || isFunction){ return ctorReturnResult; } return newObj; }Copy the code
Readers are welcome to point out any shortcomings or improvements they find. In addition, I think it is well written, and I can point a like, which is also a kind of support for the author.
Selected articles by the author
Learn how to use sentry source code and build their own front-end exception monitoring SDK. Learn how to use lodash source code and build their own functional programming library. Q: Can you simulate the js call and apply methods? Q: Can you simulate the js bind method? Q: Can you simulate the js bind method? Can simulate the implementation of the JS new operator front end using puppeteer crawler to generate the React. JS small book PDF and merge
about
Author: often with the name of Ruochuan mixed in rivers and lakes. The front road lovers | | PPT know little, only good study. Personal blog segmentfault front view column, opened front view column, welcome to pay attention to ~ gold column, welcome to pay attention to ~ github front view column, welcome to pay attention to ~ github blog, find a star^_^~
Wechat public account Ruochuan Vision
[Wakawa Vision] may be more interesting wechat public account, welcome to follow. You can also add wechat Ruochuan12, indicate the source, pull you into [front view communication group].