Home  >  Article  >  Web Front-end  >  Looking at it this way, prototypes and prototype chains don’t seem to be difficult.

Looking at it this way, prototypes and prototype chains don’t seem to be difficult.

coldplay.xixi
coldplay.xixiforward
2020-10-22 18:30:341628browse

javascriptThe column briefly and clearly introduces prototypes and prototype chains.

Looking at it this way, prototypes and prototype chains don’t seem to be difficult.

In JavaScript, prototype and prototype chain are inevitable and important concepts, so how to understand prototype and prototype chain? The following is my understanding and summary of prototypes and prototype chains. Maybe some of the understanding is still relatively shallow. As time goes by and the understanding deepens, more will be added in the future. If you find that there is something wrong with my understanding, you are welcome to correct me in the comments.

1. Why javaScript is designed as a prototype-based model

In the past learning process, we have learned from the object-oriented language java that it has three elements: encapsulation and inheritance , polymorphism. Regarding inheritance, java and javascript are actually not exactly the same.
So how is javascript designed? In the early days, browsers could only browse web content, but could not perform user interaction. That is to say, when we entered our account and password to log in, the browser could not judge the input content and needed to be judged by the server. In order to solve the problem, Netscape For this problem, invent an auxiliary scripting language that is used with java and is somewhat similar in syntax. It can be seen from this that javascript is affected by java. They are all object types. If there are objects, the inheritance mechanism will be involved. So what is the inheritance mechanism of JS?
       JS refers to the design of Java and uses the new operator to generate objects, but the difference from Java is that new is followed by Construtor instead of Class.

// java 中生成一个对象
Person p = new Person() // Person 指的是类名

// js 生成一个对象
function Person (age) {
    this.age = age
    this.nation = 'China'
}
var father = new Person(42) // Person 指的是构造函数
var mingming = new Person(11)复制代码

2. Constructor Constructor

The constructor is also an ordinary function, and it also has a prototype property. The difference from ordinary functions is that it requires the first letter to be capitalized. If the constructor is called using the new operator, it needs to perform four steps:
1. Create a new object
2. Point this to this new object
3. Execute the constructor and add properties and methods to the new object
​ 4. Return this new object

function Food (name) {
    this.name = name
    this.eat = function () {
        console.log('eat')
    }
}
var food = new Food('banana')复制代码

3. Prototype prototype

Any function has a prototype property, which points to the prototype object. Then the prototype is actually an object. The properties defined on the prototype, through inheritance (implemented by the new operator), the instantiated object also has this property.
       The relationship between prototype and constructor: There is a prototype property in the constructor, through which the prototype can be accessed.

Looking at it this way, prototypes and prototype chains don’t seem to be difficult.

Taking the code in the constructor as an example, Food is the constructor, Food.prototype is the prototype, and food is an object generated by referring to Food.prototype.

Looking at it this way, prototypes and prototype chains don’t seem to be difficult.

4. Instance

Instance refers to a constructor that creates properties and methods that can be "inherited" on the prototype and is created through the new operator Object.

Looking at it this way, prototypes and prototype chains don’t seem to be difficult.

                                                                                                                                                                   We use the new operator to create a food instance, and we can use instanceof to check the relationship between the instance and the constructor.

function Food (name) {
    this.name = name
    this.eat = function () {
        console.log('eat')
    }
}
var food = new Food('banana')  // 实例化
var res = food instanceof Food // 检查 food 是否为 Food 实例
console.log(res) // true复制代码

When we define a property on the prototype, the instance will also "inherit" this property.

function Food (name) {
    this.name = name
    this.eat = function () {
        console.log('eat')
    }
}
var food = new Food('banana')  // 实例化
var res = food instanceof Food // 检查 food 是否为 Food 实例
console.log(res) // true

// 原型定义属性
Food.prototype.type = 'object named Food'
var foodRes = food.type // 实例继承的属性
console.log(foodRes) // object named Food复制代码

5. Implicit prototype __proto__

        Any object will have a __proto__ attribute when it is created, which points to the prototype object of the constructor that generated the current object. Since this attribute is not a standard attribute, do not change the value of this attribute casually to avoid damaging the prototype chain. That is, instances can access the prototype through the __proto__ attribute.

Looking at it this way, prototypes and prototype chains don’t seem to be difficult.

        对象中的 __proto__ 属性在所有实现中是无法访问到的,但是可以通过 isPrototypeOf() 方法来确定对象之间是否存在着这种关系。

function Food (name) {
    this.name = name
    this.eat = function () {
        console.log('eat')
    }
}
var food = new Food('banana')  // 实例化
console.log(food.__proto__ === Food.prototype) // true
console.log(Food.prototype.isPrototypeOf(food)) // true复制代码

6. 构造函数 constructor

        构造函数可以通过 prototype 属性访问到原型,那么原型也是能够通过某种途径访问到构造函数的,其就是原型中的一个属性 constructor ,该属性并不是真正的构造函数,真正的构造函数是指 Constructor,两者不要混淆了。

function Food (name) {
    this.name = name
    this.eat = function () {
        console.log('eat')
    }
}
var food = new Food('banana')
console.log(Food.prototype.constructor === Food) //true复制代码

Looking at it this way, prototypes and prototype chains don’t seem to be difficult.

        关键:prototype 的 constructor 指向构造函数本身    

        那么构造函数、原型、实例三者的关系应该是这样的:

Looking at it this way, prototypes and prototype chains don’t seem to be difficult.

         为了更好地理解这一过程,我通过一个故事给大家梳理一下:
       1. 很久以前,有个雕刻家偶然看到一个很精致的花瓶(原型 Food.prototype)
       2. 一天,他想通过大批生产复刻这个花瓶来发家致富,于是他先分析这个花瓶,还原了雕刻的过程,并设计出了一条生产线(构造器 Food)
       3. 然后通过这条生产线,雕刻出许许多多的复刻花瓶。(实例 food)

7. 原型链

         proto 是任何对象都有的属性,在js中会形成一条 proto 连接起来的链条,递归访问 proto 直到值为 null ,这个搜索过程形成的链状关系就是原型链。

function Food (name) {
    this.name = name
    this.eat = function () {
        console.log('eat')
    }
}
var food = new Food('banana')  // 实例化
// 原型链
console.log(food.__proto__) // Food {}
console.log(food.__proto__.__proto__) // {}
console.log(food.__proto__.__proto__.__proto__) // null复制代码

        如下图:

Looking at it this way, prototypes and prototype chains don’t seem to be difficult.

总结

        1. 每创建一个函数都会有一个 prototype 属性,该属性是一个指针,指向一个对象,该对象为原型对象(Food.prototype)。
        2. 原型对象上的默认属性 constructor 也是一个指针,指向其相关的构造函数。
       3. 通过 new 操作符产生的实例对象都会有一个内部属性指向原型对象,该实例对象可以访问原型对象上的所有属性和方法。
       4. 实例可以通过内部指针访问到原型对象,原型对象也可以通过 constructor 找到构造函数。
       5. 每个构造函数都有一个原型对象,原型对象上包含一个指向构造函数的指针,实例包含一个指向原型对象的内部指针。
       6. __proto___ 的指向取决于对象创建时的实现方式。
       7. 构造函数实例,封装的函数,如果通过 new 操作符来调用则是构造函数,否则则不是。           8. 在整个原型链上寻找某个属性,对性能有影响,越是上层的原型对象,对性能的影响越大。
       9. js中一切皆对象,通过 new Function 的是函数对象,其构造函数是 Function,而普通对象的构造函数则是 Object 。
       10. 每一个对象都有 __proto__ 属性,而每一个函数对象才有 prototype 属性。

参考来源

1.《JavaScript 高级程序设计》
2.developer.mozilla.org/zhCN/docs/W…

最后

        如果你仔细阅读完本文,相信你对 JavaScript 中的原型和原型链会有新的认识。如果你觉得对你有帮助,记得 点赞 哦!如果你发现我理解的有问题,也欢迎你在评论中指正出来。

相关免费学习推荐:javascript(视频)

The above is the detailed content of Looking at it this way, prototypes and prototype chains don’t seem to be difficult.. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:juejin.im. If there is any infringement, please contact admin@php.cn delete