Simulated implementation of JavaScript in-depth new

Posted by cljones81 on Thu, 04 Jul 2019 02:30:47 +0200

new

In one sentence, introduce new:

The new operator creates an instance of a user-defined object type or of one of the built-in object types that has a constructor function.

Still from MDN, the reason why the Chinese version is not used is that the translation is not understood...

Let's translate this sentence ourselves:

The new operator creates an instance of a user-defined object type or a built-in object type with a constructor function.

Maybe it's a little hard to understand. Before we simulate new, let's see what new implements.

For instance:

function Person (name, age) {
    this.hobbit = 'game';

    this.name = name;
    this.age = age;
    
}

Person.prototype.strength = 100;

Person.prototype.sayName = function () {
    console.log(this.name);
}

var person = new Person('kevin', '18');

console.log(person.name) // kevin
console.log(person.hobbit) // game
console.log(person.strength) // 100

person.sayName(); // kevin

We can see that:

Instance person can

  1. Access the properties in the Person constructor

  2. Access properties in Person.prototype

Next, we can try to simulate it.

Because new is a key word, we can't directly change the effect of new, so we write a function called objectFactory to achieve the effect of new.

It is used in this way:

function Person () {
    ......
}

// var person = new Person(......);
var person = objectFactory(Person, ......)

Preliminary realization

Analysis:

Because the result of new is a new object, we also need to create a new object when we simulate the implementation, assuming that this object is called obj, because obj will have attributes in the Person constructor. Consider the classical inheritance example, we can use Person.apply(obj, arguments) to add new attributes to obj.

In the first article of the JavaScript in-depth series, we talked about prototypes and prototype chains. We know that the _proto_ attribute of an instance points to the prototype of the constructor. It is precisely because of this relationship that an instance can access the properties on the prototype.

Now, we can try to write the first edition:

// First Edition Code
function objectFactory() {

    var obj = new Object(),

    Constructor = [].shift.call(arguments);

    obj.__proto__ = Constructor.prototype;

    Constructor.apply(obj, arguments);

    return obj;

};

In this example, we

  1. A new object obj is created in the form of new Object().

  2. The first parameter is the constructor we want to pass in. In addition, because shift modifies the original array, arguments are removed from the first parameter.

  3. Point the obj prototype to the constructor so that OBJ can access the properties in the constructor prototype

  4. Using apply, change the direction of this to the new object so that obj can access the attributes in the constructor

  5. Return to obj

If you're not sure about the prototype chain, you can see JavaScript Deeply from Prototype to Prototype Chain.
If the apply part is not very clear, you can see "JavaScript in-depth call and apply simulation implementation"
If classical inheritance is not very clear, you can see "JavaScript in-depth inheritance", but has not yet been released, haha

Copy the following code into the browser, we can do a test:

function Person (name, age) {
    this.hobbit = 'game';

    this.name = name;
    this.age = age;
    
}

Person.prototype.strength = 100;

Person.prototype.sayName = function () {
    console.log(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(Person, 'kevin', '18')

console.log(person.name) // kevin
console.log(person.hobbit) // game
console.log(person.strength) // 100

person.sayName(); // kevin

[]~( ̄▽ ̄)~**

Return Value Effect Implementation

Next, let's look at a case where the constructor has a return value, for example:

function Person (name, age) {

    this.strength = 10;
    this.age = age;

    return {
        name: name,
        hobbit: 'game'
    }
    
}

var person = new Person('kevin', '18');

console.log(person.name) // kevin
console.log(person.hobbit) // game
console.log(person.strength) // undefined
console.log(person.age) // undefined

In this example, the constructor returns an object, and in the instance person only the attributes in the returned object can be accessed.

Also, notice that here we return an object, what if we just return a value of the basic type?

Another example is:

function Person (name, age) {

    this.strength = 10;
    this.age = age;

    return 'handsome boy';
    
}

var person = new Person('kevin', '18');

console.log(person.name) // undefined
console.log(person.hobbit) // undefined
console.log(person.strength) // 10
console.log(person.age) // 18

The result is completely reversed. This time, although there is a return value, it is equivalent to no return value for processing.

So we also need to determine whether the returned value is an object, if it is an object, we return the object, if not, what we should return and what we should return.

Look at the second edition of the code, the last edition of the code:

// Second edition 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;

};

Related links

JavaScript Deeply from Prototype to Prototype Chain

"JavaScript in-depth call and application simulation implementation"

Deep Inheritance of JavaScript hasn't been released yet

In-depth series

JavaScript Deep Series Directory Address: https://github.com/mqyqingfeng/Blog.

JavaScript in-depth series is expected to write about 15 articles, aiming to help you understand the underlying knowledge of JavaScript, focusing on such difficult concepts as prototype, scope, execution context, variable object, this, closure, by value delivery, call, apply, bind, new, inheritance and so on.

If there are any mistakes or inaccuracies, please be sure to correct them. Thank you very much. If you like it or are inspired by it, welcome star, which is also an encouragement to the author.

Topics: Javascript Attribute github