I. Concepts of prototype and __proto__
Prototype is a property of a function (each function has a prototype property), and this property is a pointer to an object. It is a property that displays the prototype of the modified object.
__proto__ is a built-in property owned by an object (note: Prototype is a built-in property of a function, __proto__ is a built-in property of an object), and is a property of JS internal use to find the prototype chain. (a function is also an object, an object created through function)
Ii. process of new
var person = function () {};var p = new person ();
The new process is split into the following three steps:
(1) var p={}; In other words, initialize an object p
(2) p.__proto__ = Person.prototype;
(3) Person.call (p); That is, construct p, which can also be called initialization P
The key is the second step, and let's prove it:
var person = function () {};var p = new person (); alert (p.__proto__ = = = Person.prototype);
This piece of code returns TRUE. Note that our step 2 is correct.
Iii. examples
var function (){}; function () { alert ("My Name is Jacky"); }; =; var New Person (); P.sayname ();
P is an object that refers to a person. We define a Sayname method and an age property on the person's prototype, and when we execute p.age, we will first look inside this (that is, inside the constructor), if not found and then back up the prototype chain.
How is the upward trace up here? This is where you use the __proto__ property to link to the prototype (that is, person.prototype) to find it. Finally, the age attribute was found on the prototype.
__proto__ of all constructors/functions point to Function.prototype, which is an empty function
| 123456789 |
Number.__proto__ === Function.prototype // trueBoolean.__proto__ === Function.prototype // trueString.__proto__ === Function.prototype // trueObject.__proto__ === Function.prototype // trueFunction.__proto__ === Function.prototype // trueArray.__proto__ === Function.prototype // trueRegExp.__proto__ === Function.prototype // trueError.__proto__ === Function.prototype // trueDate.__proto__ === Function.prototype // true |
There is a total of 12 built-in (build-in) constructors/objects in JavaScript (new JSON in ES5), and 8 constructors are listed here. As the rest of the global cannot be accessed directly, arguments is only created by the JS engine when the function is called, and Math,json exists as an object without new. Their __proto__ are object.prototype. As follows
| 12 |
Math.__proto__ === Object.prototype // trueJSON.__proto__ === Object.prototype // true |
The "all constructors/functions" mentioned above certainly includes a custom. As follows
| 123456 |
// 函数声明functionPerson() {}// 函数表达式varMan = function() {}console.log(Person.__proto__ === Function.prototype) // trueconsole.log(Man.__proto__ === Function.prototype) // true |
What does that mean?
All constructors come from Function.prototype, even the root constructor object and the function itself. All constructors inherit the properties and methods of the Function.prototype. such as length, call, apply, bind (ES5).
Function.prototype is also the only prototype that typeof Xxx.prototype as "function". The prototype of other constructors is an object. As follows
| 12345678910 |
console.log(typeofFunction.prototype) // functionconsole.log(typeofObject.prototype) // objectconsole.log(typeofNumber.prototype) // objectconsole.log(typeofBoolean.prototype) // objectconsole.log(typeofString.prototype) // objectconsole.log(typeof Array.prototype) // objectconsole.log(typeofRegExp.prototype) // objectconsole.log(typeofError.prototype) // objectconsole.log(typeofDate.prototype) // objectconsole.log(typeofObject.prototype) // object |
Oh, the above also mentions that it is an empty function, alert (function.prototype) look under.
Knowing that all constructors (with built-in and custom) __proto__ are Function.prototype, who is Function.prototype __proto__?
I believe I have heard that the function in JavaScript is also a class citizen, where can it be manifested? As follows
| 1 |
console.log(Function.prototype.__proto__ === Object.prototype) // true |
This means that all constructors are also a common JS object, which can add/remove attributes to the constructor, and so on. It also inherits all the methods on Object.prototype: ToString, ValueOf, hasOwnProperty, and so on.
Who was the last Object.prototype __proto__?
| 1 |
Object.prototype.__proto__ === null// true |
has been to the top, null.
The __proto__ of all objects point to the prototype of their constructors
The above tests all the built-in constructors and the __proto__ of the custom constructors, and then look at who the __proto__ of all the instance objects of these constructors point to?
First look at the JavaScript engine built-in constructor
| 1234567891011 |
varobj = {name: ‘jack‘}vararr = [1,2,3]varreg = /hello/gvardate = newDatevarerr = newError(‘exception‘)console.log(obj.__proto__ === Object.prototype) // trueconsole.log(arr.__proto__ === Array.prototype) // trueconsole.log(reg.__proto__ === RegExp.prototype) // trueconsole.log(date.__proto__ === Date.prototype) // trueconsole.log(err.__proto__ === Error.prototype) // true |
Then look at the custom constructor, where a person is defined
| 12345 |
functionPerson(name) { this.name = name}var p = newPerson(‘jack‘)console.log(p.__proto__ === Person.prototype) // true |
P is an instance object of person, and the internal prototype of P always points to the prototype of its constructor person.
Each object has a constructor property that can get its constructor, so the following print results are also identical
| 12345 |
functionPerson(name) { this.name = name}var p = newPerson(‘jack‘)console.log(p.__proto__ === p.constructor.prototype) // true |
The person above does not add a property or method to its prototype, which adds a GetName method to its prototype
| 12345678 |
functionPerson(name) { this.name = name}// 修改原型Person.prototype.getName = function() {}varp = new Person(‘jack‘)console.log(p.__proto__ === Person.prototype) // trueconsole.log(p.__proto__ === p.constructor.prototype) // true |
You can see that both p.__proto__ and person.prototype,p.constructor.prototype are identical, meaning they all point to the same object.
If you set up a prototype in a different way, the result is a little differently.
| 12345678910 |
functionPerson(name) { this.name = name}// 重写原型Person.prototype = { getName: function() {}}varp = newPerson(‘jack‘)console.log(p.__proto__ === Person.prototype) // trueconsole.log(p.__proto__ === p.constructor.prototype) // false |
The Person.prototype is rewritten directly here (note: The previous example was to modify the prototype). The output shows that p.__proto__ still points to person.prototype, not p.constructor.prototype.
It's also good to understand that assigning a value to Person.prototype is an object with a direct amount of {getname:function () {}}, an object whose constructor (constructor), which is defined using the object's direct amount, points to the root constructor object, Object.prototype is an empty object {},{} is naturally not equal to {getname:function () {}}. As follows
| 1234 |
varp = {}console.log(Object.prototype) // 为一个空的对象{}console.log(p.constructor === Object) // 对象直接量方式定义的对象其constructor为Objectconsole.log(p.constructor.prototype === Object.prototype) // 为true,不解释 |
The __proto__ used in the above code is currently not supported in IE6/7/8/9. You can use Object.getprototypeof (ES5) in IE9 to get an internal prototype of an object.
| 123 |
varp = {}var__proto__ = Object.getPrototypeOf(p)console.log(__proto__ === Object.prototype) // true |
JS's __proto__ and prototype