JavaScript — 理解prototype与class

一步一步捋清prototype

前言

  • 学习JavaScript,不可避免地要学习JS中的面向对象的编程模式,但JS中的OOP和c++,java等典型的面向对象语言明显不一样,“原型链”,es6中的“class”,都彰显着js中面向对象的不同凡响。
  • 究竟什么是原型prototype呢?如何在JavaScript中实现“类”呢?

一张图

图片描述

图片分析

这是我总结的一张图片,简单的描绘了原型和构造函数、实例间的复杂关系。java

  1. 全局对象window属性Object(此处仅用来举例,其他属性暂且不提),指向Object()这个函数对象
  2. Object中存着prototype,它指向了原型(原型中包含了对象的全部方法和属性)
  3. 当咱们声明一个实例let obj = new Object(), 你能够发现它天生就带着__proto__属性。而__proto__居然和Object.prototype指向了同一个对象。咱们知道,它就是原型
    clipboard.png

一些思考

1.Object.prototype(即对象的原型)的原型是什么呢?c++

  • 咱们不妨打印出来试一试:clipboard.png
    应该和你想的同样,对象的原型就是原型链的尽头了,它只是一个普通的对象,并无原型。

2.Object.prototype中的constructor是什么?有什么用?es6

  • 你应该还记得咱们刚刚像这样let obj = new Object();建立了一个对象实例obj,那么再来看看这个,你应该就一目了然了
    clipboard.png
    没错,constructor存在的意义就是为了让实例化地对象找到它的构造函数。(对实例化的数组,constructor指向Array;对实例化地函数,constructor指向Function)

3.但你不能人为constructor指向的必定是构造出当前对象的函数。编程

  • 例如,你能说出Object.prototype.constructor指向谁吗?clipboard.png
    你看,这个结果是否是很让人头大??Object.prototype指向了原型,而原型的constructor的又指回了Object。实际上这种试验是无心义的,由于咱们要知道,constructor是提供给实例,用来定位它的构造函数的属性,而不是给原型自己使用的。
  • 而这种Object.prototype.constructor ===Object的现象,其实源于人为设计。为了让实例的对象都继承原型中的constructor,没法避免出现这种现象。

4.咱们尝试更深刻一些?尝试剖析一下数组对象的相关结构。数组

  • 问题1:Array.prototype.__proto__===?函数

    • 直接来看结果吧clipboard.png
    • 为何会有这种结果呢?其实咱们只须要理解清Array.prototype的本质就行了,其实Array.prototype只是一个Object()构造出的对象实例而已,一个对象实例的原型固然是Object.prototype啊!换句话说Array.prototype和obj在本质上是同样的!
  • 问题2:let arr=[1,2,3]; clipboard.png 属于对象的方法hasOwnProperty是如何在数组实例上生效的呢?学习

    1. arr在自身寻找hasOwnProperty方法,发现没有。
    2. arr又到他爸爸arr.__proto__即Array.prototype中寻找hasOwnProperty方法,仍然找不到 =
    3. arr再到他爷爷arr.__proto__.__proto__即Object.prototype中寻找,找到了这个方法,因而arr调用了这个方法。

类和继承

  1. class的默认属性this

    class Person {
       name = 'Oliver'
       sayHi = ()=>{ console.log(hi) }
    }

    在class声明中
    经过 = 赋值的属性,会变成该class实例的属性默认值;
    经过箭头函数声明的方法,会挂载到该实例身上,而非class身上。spa

  2. 方法的重写prototype

    // Person定义同上
    class Child extends Person{
       sayHi(){
           console.log('I am a child.')
           super.sayHi()
       }
    }

    子类重写父类的方法后,若是还想调用父类的方法,须要使用 super 关键字,super上挂载有父类的原始方法。

  3. class vs prototype

    // prototype方法
       function Person( name, age) {
              this.name = name,
               this.age = age
       }
       Person.prototype.sayHi = function() {
           console.log('你好,我叫'+this.name);
       }
       
       //class方法
    class Person{
       constructor(name,age){
           this.name = name;
           this.age = age;
       }
       sayHi(){ console.log('你好,我叫'+this.name); }
    }
  4. 继承

    class Children extends Person{
        constructor(name,age,grade){
            super(name,age);
            this.grade = grade;
        }
        sayGrade(){
            console.log('我今年${grade}年级');
        }
    }

conclusion

  • class只是prototype方法的语法糖而已,本质上没有区别
  • 运用顺序:理解prototype => 熟练使用prototype => 无压力使用class
相关文章
相关标签/搜索