zoukankan      html  css  js  c++  java
  • 原型、原型对象、构造函数、原型链理解

    1. 基本概念:

    “原型属性”也可以叫做“原型”(prototype):所有函数都有prototype,我觉得可以理解为python中的类属性,不需要通过实例,直接用类(es5就是函数名)可以调用,下面列举了三种创建函数的方法,函数创建后都有prototype属性,prototype指向“原型对象”。

    // 函数声明
    function F1() {
    };
    // 表达式定义
    let F2 = function () {
    };
    // 函数构造
    let F3 = new Function('n1', 'n2', 'return n1+n2');
    
    console.info(F1.prototype)    //F1 {}
    console.info(F2.prototype)    //F2 {}
    console.info(F3.prototype)    //anonymous {}

    原型对象(prototype所指向的对象):这玩意主要就是用来继承用的,包含实例的方法和属性。说白了也就是一个对象,用来定义函数对象的属性、方法,默认情况下它包含一个constructor属性,如果你重新定义可以覆盖constructor属性。

    原型对象与构造函数配合一起,就形成一个类了,然后构造函数接收每次初始化对象的初始值,原型对象就提供类模板。而在其他java、python中都写在class中,当然es6也加入了class;以下的简单代码帮助理解上面说的,定义一个动物类,根据构造函数创造不同的动物,如果需要创建特殊动物,可以继承然后添加一些特殊属性、方法再创建。---------总结es5的类可以用“构造函数+构造函数的prototype”来定义,类的对象使用“new构造函数”来生成。

    // 构造函数
    let Animal = function (name) {
        this.name = name
    }
    // 原型对象定义
    Animal.prototype.getAnimal = function () {
        return this.name
    }
    // 创建对象,会继承Animal.prototype
    let dog = new Animal('dog')
    let cat = new Animal('cat')
    console.info(dog.getAnimal())
    console.info(cat.getAnimal())

     

    上图展示了构造函数、原型对象、具体对象的属性、方法及属性值。

    普通对象与函数对象:通过函数对象 new一下可以得到普通对象,把函数对象理解为类,普通对象为实例。如下代码加强理解,可以看到函数对象new完以后生产的对象是object;函数对象中都有prototype前面已经说过了(为什么函数对象中会有这个属性以后读取更深以后再解答)

    // Animal函数对象
    let Animal = function (name) {
        this.name = name
    }
    // 原型对象
    Animal.prototype.getAnimal = function () {
        return this.name
    }
    // 通过函数对象创建普通对象
    let dog = new Animal('dog')
    console.info(typeof dog)    //object

    总结: 函数对象通过new Function()可以得到,Function对象可以构造函数对象。而函数对象又可以new一个普通对象出来。

    __proto__:所有对象都有__proto__这个属性,这个属性指向对应“函数对象(就理解为类)”的prototype,这也是实现原型链的根本,在书中一般都用[[prototype]]。

    构造函数和constructor属性:其实前面的图已经标注了,概念后续补上。

    原型链:ES中的继承主要用原型链来实现,记住了这玩意主要用来实现继承。其基本思想是:利用原型让一个引用类型继承另一个引用类型的属性和方法(js高级程序设计说的),还是用以上的例子来说明

    let Animal = function (name) {
        this.name = name
    }
    // 原型对象定义
    Animal.prototype.getAnimal = function () {
        return this.name
    }
    // 创建对象,会继承Animal.prototype
    let dog = new Animal('dog')
    let cat = new Animal('cat')
    console.info(dog.valueOf())
    console.info(cat.valueOf())

    跟上面例子就差了最后console打印部分,我们定义的Animal没有写valueof()为什么可以调用这个方法呢?到底是什么鬼?这就是原型链搞的鬼。我再把上面的图形完善一下

    上图还有两个属性的指向没有画,第一、Animal的__proto__指向;第二、Animal.prototype的__proto__指向。

    这个图把Animal.prototype的__proto__指向添加了,

    图形说明:

    1. Animal.prototype是个普通对象,ES中Object是所有对象的基础。所有引用类型都继承了Object;所有函数的默认原型是都Object的实例,因此Animal.prototype的__proto__指向Object.prototype,这个一定要理解。

    2. 我们调用cat.valueOf()解释器会先找dog实例中有没有这个方法,没有就在Animal.prototype中查找,没有再去Object.prototype中查找。然后就有了cat.valueOf()的运行结果:Animal { name: 'cat' }。

    3. Object构造函数的prototype也指向Object.prototype。

    最后把Animal的__proto__指向补完基本就差不多了。

  • 相关阅读:
    HttpServletRequest request 获取form参数的两种方式
    mysql中计算两个日期的时间差函数TIMESTAMPDIFF用法
    Better exception message for missing @RequestBody method parameter
    下载Xcode历史版本方法
    CGLib与JDK的动态代理
    LeetCode: Longest Consecutive Sequence [128]
    POJ训练计划2777_Count Color(线段树/成段更新/区间染色)
    JBoss AS 7性能调优(三)
    java的Future使用方法
    Redis学习资源
  • 原文地址:https://www.cnblogs.com/caoyi/p/10166831.html
Copyright © 2011-2022 走看看