Why assign something to Something.prototype.constructor?

I read about how the Javascript prototype property works along with inheritance, and then started looking at Angular.js code and came up with some questions.

First, I read that the prototype property points to an object that has a constructor property that points to the original function that is used to create the object. For example:

// This is the constructor function Shape() { this.position = 1; } // The constructor points back to the original function we defined Shape.protoype.constructor == Shape; 

The prototype also contains any other methods or properties that were defined on it by us or the Javascript language itself, and they are shared by all instances of the object. If you want the object to inherit from Shape, you need to set the square prototype equal to the new Shape instance, because the internal [[prototype]] property for Square.prototype gets the value of the public object of the Shape.prototype property.

 function Square() {} Square.prototype = new Shape(); var square = new Square(); square.position; // This will output 1 

It all makes sense to me.

However, the Angular.js code I have a question for seems to be related to all of this, but does what I don't understand. It doesn't seem to be related to inheritance, so I can understand why there should be no differences, but I just wonder why they wrote it the way they did it.

Inside Angular.js there is a HashMap object and a Lexer object, but they are defined differently, but they seem to be created and used exactly the same. First, the Lexer constructor is defined, and then they install the prototype in the object literal containing the methods that should be used by all Lexer instances. All this makes sense. I don’t understand why they define the "constructor" property and set it only to "Lexer" if they are not for the HashMap below.

 var Lexer = function(options) { this.options = options; }; // Notice they specify Lexer as the constructor even though they don't for HashMap below Lexer.prototype = { constructor: Lexer, lex: function(text) { ... }, is: function(ch, chars) { ... }, peek: function(i) { ... }, isNumber: function(ch) { ... }, isWhitespace: function(ch) { ... }, isIdent: function(ch) { ... }, isExpOperator: function(ch) { ... }, throwError: function(error, start, end) { ... }, readNumber: function() { ... }, readIdent: function() { ... }, readString: function(quote) { ... } }; 

Then, if you look at the HashMap code, they do the same, except that they do not specify a constructor property. Why is this? It seems to work the exact same way, and I tested that the constructor is still called.

 // The HashMap Constructor function HashMap(array, isolatedUid) { if (isolatedUid) { var uid = 0; this.nextUid = function() { return ++uid; }; } forEach(array, this.put, this); } HashMap.prototype = { put: function(key, value) { ... }, get: function(key) { ... }, remove: function(key) { ... } }; 

So, the property of the constructor is optional if there is no inheritance, so maybe one person wrote Lexer and the other HashMap, and someone decided to specify the constructor?

+6
source share
1 answer

By default, each prototype has a constructor property that refers to the function to which it belongs.

 function A() { } console.log(A.prototype.constructor === A); // true 

If you completely overwrite the prototype with an object literal or with some other constructed prototype, this constructor value will be erased and remain undefined or another value.

 function A() { } A.prototype = { greeting: "Hello!" }; console.log(A.prototype.constructor === A); // false 

The constructor prototype property is not required for the constructor to work properly, but people often reassign prototype.constructor back to their initial value to maintain consistency, and what you see for Lexer .

Consider:

 function A() { } function B() { } B.prototype = Object.create(A.prototype); var b = new B(); console.log(b.constructor === A); // true console.log(b.constructor === B); // false B.prototype.constructor = B; console.log(b.constructor === A); // false console.log(b.constructor === B); // true 

One can only guess why this was excluded for HashMap . I doubt that this was done for some good reason, and perhaps it was just supervision.

+8
source

Source: https://habr.com/ru/post/982959/


All Articles