In JavaScript, a function is an object of type Function
that contains properties and methods. The prototype (Prototype)
is an attribute of Function
type object.
The prototype
attribute is included when the function is defined, and its initial value is an empty object. There is no prototype type defined for functions in JavaScript, so the prototype can be of any type.
The prototype is used to save the shared properties and methods of the object . The properties and methods of the prototype do not affect the properties and methods of the function itself.
// Properties of Function type -> properties that all functions have console.log(Function.prototype); //[Function] //Define function function fn() { console.log('this is function'); } //The default value of the prototype is the empty object console.log(fn.prototype); //fn {} // The function contains a constructor --> all reference types are actually constructors console.log(Number.prototype); //[Number: 0] console.log(Object.prototype);//{}
You can get the prototype of the object in the following two ways to set shared properties and methods:
prototype
attribute of the constructorgetPrototype
of the Object object (obj) method.function fn() { console.log('this is function'); } //Use the attribute syntax structure of the access object console.log(fn.prototype); //fn {} console.log(fn['prototype']);//fn {} //Object type provides getPrototypeOf() method console.log(Object.getPrototypeOf(fn)); //[Function]
Object.getOwnPropertyDescriptors()
method is used to obtain the descriptors of all its own properties of an object.
var result = Object.getOwnPropertyDescriptor(Object.prototype,'constructor'); console.log(result) //The output results are as follows: //{ // value: [Function: Object], // writable: true, // enumerable: false, // configurable: true // }
constructor是在创建函数的时候自动添加的,指向构造函数本身
You can set the properties and methods of the prototype in the following two ways:
Constructor.prototype.Attribute name = attribute value; Constructor.prototype.Method name = function(){};
When we need to add many attributes to the prototype, it is too troublesome to write
构造函数.prototype.属性名
over and over again. We can directly modify the entireprototype
constructor.prototype = { Attribute name: attribute value, Method name: function(){}}
function foo () {}foo.prototype = { constructor: foo, name: 'jam', age: 18, address: 'Beijing'}var fn = new foo()console.log(fn.address) //Beijing
Each object will have an isPrototypeOf()
method, which is used to determine a Whether the object is a prototype of another object.
The sample code is as follows: // Define the object through initializer var obj = { name:'jam' } //Define constructor function Hero() {} // Assign the object obj to the prototype of the constructor Hero Hero.prototype = obj; // Create object through constructor var hero = new Hero(); // The isPrototypeOf() method determines whether the specified object is the prototype of another object var result = obj.isPrototypeOf(hero); console.log(result);//true
verifies that
obj
object is the prototype ofhero
object
Next we use a piece of code to expand our understanding of the prototype chain:
Scenario: Find the objects on the obj object Steps performed by address attribute js: 1. The get operation will be triggered. 2. Search the attribute in the current object. 3. If it is not found, it will search on the prototype chain (__proto__) object at this time. 1. The search will end. 2. If it is not found, it will continue to search along the prototype chain. Until the top-level prototype is found (what the top-level prototype is is temporarily unclear)
var obj = { name: 'jam', age: 19 } /* Requirement: Find the address attribute on the obj object*/ // The prototype chain is searched layer by layer. If it is not found, it will be searched until the top-level prototype is found. obj.__proto__ = {} obj.__proto__.__proto__ = {} obj.__proto__.__proto__.__proto__ = { address: 'Beijing' } console.log(obj.address) // Beijing console.log(obj.__proto__.__proto__.__proto__) // { address: 'Beijing' }
Finally find the address attribute
那么这里有一个问题,如果一直没有查到,会无穷尽的去查找吗?接下来我们就来了解一下
As we mentioned above, we will not search endlessly along the prototype chain. When the top-level prototype is found, undefined
will be returned if it has not been found yet.
So what is the top-level prototype?
The sample code is as follows:
var obj = { name: 'jam' }console.log(obj.__proto__) // {}console.log(obj.__proto__.__proto__) //
The prototype of null literal object obj is:
{}
.{}
is the top-level prototype. When we continue to print__proto__
upwards, a null value is returned, which proves that the previous layer is already the top-level prototype.
The following figure is a supplement to the top-level prototype that is missing in the first piece of code:
顶层原型就是Object.prototype
3.1 So where is the end of the prototype chain? For example, does the third object also have a prototype __proto__
attribute?
var obj = {name:'jam'}obj.__proto__ = {}obj.__proto__.__proto__ = {}obj.__proto__.__proto__.__proto__ = {}console.log(obj.__proto__.__proto__.__proto__.__proto__) // {}
We found that the above printed result is空对象{}
var obj = { name: 'jam', age: 19 } console.log(obj.__proto__) // {} console.log(Object.prototype) // {} console.log(obj.__proto__ === Object.prototype) // true
Object is the parent class of all classes, so obj.__proto__ is actually Object.prototype,
console.log(obj.__proto__ === Object.prototype) // true
we can see that the result Object.prototype is the top-level prototype.
{}
3.2 Then we may ask: {}
Is there anything special about prototypes?
console.log(obj.__proto__.__proto__.__proto__.__proto__.__proto__) // null
Object.prototype
is an empty object {}, it is not empty, but the properties inside are not enumerable. For example, let’s print constructor
property to see <!-- It can be seen that there is a constructor attribute and it is not empty -->console.log(Object.prototype.constructor) // [Function: Object] <!-- constructor refers back to Object -->
Object.prototype
through the Object.getOwnPropertyDescriptors()
method. console.log(Object.getOwnPropertyDescriptors(Object.prototype)) //As shown in the long screenshot below