In part 12 of this JavaScript in-depth series, we’ll uncover the truth about using new to get an instance of a constructor
new
New:
The new operator creates an instance of a user-defined object type or one of the built-in object types that has a constructor
It might be a little confusing, but let’s see what New implements before we simulate it.
Here’s an example:
// Otaku
function Otaku (name, age) {
this.name = name;
this.age = age;
this.habit = 'Games';
}
// Due to lack of exercise, the physical strength is worrying
Otaku.prototype.strength = 60;
Otaku.prototype.sayYourName = function () {
console.log('I am ' + this.name);
}
var person = new Otaku('Kevin'.'18');
console.log(person.name) // Kevin
console.log(person.habit) // Games
console.log(person.strength) / / 60
person.sayYourName(); // I am KevinCopy the code
From this example, we can see that the instance person can:
- Access a property in the Otaku constructor
- Access the properties in otaku.prototype
Now, we can try to simulate it.
Because new is a keyword, it cannot be overridden directly like bind, so we write a function named objectFactory to simulate the effect of new. Here’s how it works:
function Otaku () {
……
}
/ / use the new
var person = newOtaku (...) ;/ / use the objectFactory
varThe person = objectFactory (Otaku,...)Copy the code
The preliminary implementation
Analysis:
Because the result of new is a new object, so when we simulate it, we’re also going to create a new object, let’s say that object is called obj, because obj is going to have properties in the Otaku constructor, so if you think about the classic inheritance example, You can use otaku.apply (obj, arguments) to add new attributes to obj.
In the first part of our JavaScript In-depth series on prototypes and prototype chains, we learned that the instance’s __proto__ attribute refers to the constructor’s prototype, and that by establishing this relationship, the instance has access to the attributes on the prototype.
Now, we can try to write the first edition:
// First version of the code
function objectFactory() {
var obj = new Object(),
Constructor = [].shift.call(arguments);
obj.__proto__ = Constructor.prototype;
Constructor.apply(obj, arguments);
return obj;
};Copy the code
In this edition, we:
- Create Object obj with new Object()
- Take the first argument, which is the constructor we’re passing in. Also, since shift modifies the array, arguments will be removed from the first argument
- Point obj’s stereotype to the constructor so that obj can access properties in the constructor stereotype
- Using apply, change the reference of the constructor this to the new object so that obj can access the properties in the constructor
- Returns the obj
More on:
Prototypes and prototype chains, you can see JavaScript Deeper from Prototypes to Prototype Chains
Apply, you can see JavaScript In-depth Call and Apply simulation Implementation
Classic inheritance, you can see inheritance in JavaScript Deep
Copy the following code into the browser and we can test it:
function Otaku (name, age) {
this.name = name;
this.age = age;
this.habit = 'Games';
}
Otaku.prototype.strength = 60;
Otaku.prototype.sayYourName = function () {
console.log('I am ' + this.name);
}
function objectFactory() {
var obj = new Object(),
Constructor = [].shift.call(arguments);
obj.__proto__ = Constructor.prototype;
Constructor.apply(obj, arguments);
return obj;
};
var person = objectFactory(Otaku, 'Kevin'.'18')
console.log(person.name) // Kevin
console.log(person.habit) // Games
console.log(person.strength) / / 60
person.sayYourName(); // I am KevinCopy the code
[]~( ̄▽ ̄)~**
Return value effect implementation
Let’s look at another case where the constructor has a return value. Here’s an example:
function Otaku (name, age) {
this.strength = 60;
this.age = age;
return {
name: name,
habit: 'Games'}}var person = new Otaku('Kevin'.'18');
console.log(person.name) // Kevin
console.log(person.habit) // Games
console.log(person.strength) // undefined
console.log(person.age) // undefinedCopy the code
In this case, the constructor returns an object, and only properties in the returned object can be accessed in the instance Person.
Also, notice that we’re returning an object here. What if we just returned a value of a primitive type?
Here’s another example:
function Otaku (name, age) {
this.strength = 60;
this.age = age;
return 'handsome boy';
}
var person = new Otaku('Kevin'.'18');
console.log(person.name) // undefined
console.log(person.habit) // undefined
console.log(person.strength) / / 60
console.log(person.age) / / 18Copy the code
The result is completely reversed. This time there is a return value, but it is equivalent to no return value to process.
So we also need to determine whether the value returned is an object, if it is an object, we return that object, if it is not, we return whatever we should return.
Take a look at the second and final version of the code:
// The second version of the code
function objectFactory() {
var obj = new Object(),
Constructor = [].shift.call(arguments);
obj.__proto__ = Constructor.prototype;
var ret = Constructor.apply(obj, arguments);
return typeof ret === 'object' ? ret : obj;
};Copy the code
Next article
JavaScript dives into such array objects with Arguments
A link to the
JavaScript In Depth from Prototype to Prototype Chain
JavaScript In-depth Call and Apply simulation implementation
JavaScript Deep Inheritance
In-depth series
JavaScript in-depth series directory address: github.com/mqyqingfeng… .
JavaScript in-depth series is expected to write about 15, aimed at helping you understand the underlying knowledge of JavaScript, focusing on such as prototypes, scope, execution context, variable objects, this, closures, passing by value, call, apply, bind, new, inheritance and other difficult concepts.
If there are any mistakes or irregularities, please be sure to correct them. Thank you very much. If you like it or have some inspiration, welcome star, which is also a kind of encouragement to the author.