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:

  1. Access a property in the Otaku constructor
  2. 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:

  1. Create Object obj with new Object()
  2. 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
  3. Point obj’s stereotype to the constructor so that obj can access properties in the constructor stereotype
  4. Using apply, change the reference of the constructor this to the new object so that obj can access the properties in the constructor
  5. 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.