• 原型对象


    1 什么是原型对象

    1.1 从一段代码开始认识显式原型对象

    function FU(){
    
    }
    console.log(FU.prototype)

      在上面代码中,定义了一个叫做FU的函数

      然后我们打印了这个函数的一个属性,属性名字叫做prototype,打印结果如下图,prototype指向的对象就是这个函数的原型对象(先不关心它的内容),这个属性prototype就叫做显式原型对象

      

      prototype这个属性指向的对象实际上是一个Object的实例对象,如下代码,输出为true

    console.log(FU.prototype instanceof Object)  //true

      结论一:每一个函数都有一个prototype属性,这个属性是一个Object的实例对象,它就是这个函数的原型对象,这个属性prototype叫做显示原型对象

     

    1.2 从一段代码开始认识隐式原型对象

    let f = new FU()
    console.log(f.__proto__)

    上面代码创建一个FU()函数的实例f,同时打印了f的一个叫做__proto__的属性,这个属性指向的对象也是函数的原型对象,这个个属性__proto__叫就做隐式原型对象,如下图

       结论二:每一个实例对象都有一个__proto__属性,这个属性是一个Object的实例对象,它就是这个函数的原型对象,这个属性__proto__叫做隐示原型对象

     

    1.3 对比显式和隐式原型对象

      可以对比下显式原型对象和隐式原型对象的内容,发现象内容一样,再通过下面代码输出为true,证明显式原型对象和隐式原型对象指向的是同一个对象

    console.log(FU.prototype === f.__proto__)  //true

      结论三:显式原型对象和隐式原型对象指向的是同一个实例对象,也就是说函数或者说函数实例的原型对象只有一个,函数的prototype属性(显式)和函数实例的__proto__属性(隐式)都指向它

     

    1.4 其它事项

     prototype 属性和__proto__在什么时候创建的

      我们在定义一个函数的时候,js会自动为这个函数添加一个属性叫做prototype ,指向一个Object对象(也是js根据这个函数创建的)

    function FU(){
      //prototype = {...}
    }

      在创建函数实例的时候,js会自动为这个实例添加一个__proto__属性,并且这个属性的值等于函数的prototype 

    let f = new FU()
    //f.__proto__ =FU.prototype

     

    2 原型对象和构造函数的关系

      还是和上面一样,定义一个函数FU,打印它的原型对象,发现原型对象里面有一个属性叫做constructor,如下图

    function FU(){
    
    }
    
    console.log(FU.prototype)

       再执行以下代码,发现这个constructor 等于这个函数

    console.log(FU.prototype.constructor === FU)

      同理,f.__proto__.constructor也等于这个函数

    let f = new FU()
    console.log(f.__proto__.constructor === FU)
    console.log(f.__proto__.constructor === f.constructor)

      结论四:函数的原型对象的constructor执行这个函数本身,也就是说,函数和原型对象是相互指向的,函数的prototype属性指向原型对象,原型对象的constructor 有指向这个函数

     

    3 关于函数的几个知识

    3.1 函数本身也是一个对象

      函数都是通过Function函数创建的  

      我们通常定义一个函数,采用如下写法

    let fu  = function FU(){
    
    }

      它等同于

    let fu = new Function()

      

    3.2 函数这个对象的__proto__属性

      下面代码执行结果为true

      首先函数FU也是个对象,且函数FU这个对象是函数Function的实例对象,所以函数FU这个对象的__proto__属性指向函数Function的prototype,都指向的是Function的原型对象,所以下面代码执行为true

    let fu = function FU(){
    
    }
    console.log(fu.__proto__ === Function.prototype) //true

      再看一个特殊的函数对象Function

      下面代码执行结果为true,说明函数Function本身同时通过函数FUNCTION创建的,是不是特别神奇

    let func = Function
    console.log(func.__proto__ === Function.prototype) //true
     console.log(fu.constructor === fu) //true

      结论五:所有函数本身都是通过函数Function创建的(包括函数Function本身),所有函数本身是函数Function的实例对象,所以所有函数的__proto__属性都指向Fucntion的prototype属性

    4 原型链

      上面说了,原型对象是一个Object对象,既然是一个Object对象,那么也会有__proto__属性

        let fu = function(){
    
        }
        
        let p1 = fu.__proto__
        console.log(p1)  //函数FU的原型对象
        let p2 = p1.__proto__
        console.log(p2) //函数Object的原型对象
        let p3 = p2.__proto__
        console.log(p3) //null  函数Object的原型对象的原型对象

      如上代码,函数FU的原型对象p1,它是一个Object对象,所以它的原型对象p2就是Object函数的原型对象,p2作为函数Object的原型对象,也是一个Object对象,它的原型对象指向null,这形成了一个链条,且这个链条到函数Object的原型对象就结束了。

    5 实例及原型对象的属性问题

    5.1 定义函数时的属性及实例对象上添加的属性

      定义函数时定义的属性不会出现在原型对象上

      实例上添加的属性也不会出现在原型对象上

        function FU(name,age){
            this.name = name
            this.age = age
        }
    
        let f = new FU('HAHA',18)
        f.sex = ''
        console.log(f) //FU {name: 'HAHA', age: 18, sex: '男'}
        console.log(FU.prototype.name)  //undefined
        console.log(FU.prototype.age)  //undefined
        console.log(FU.prototype.sex)  //undefined

      

    5.2 属性和原型链

      原型对象上的属性不会直接出现在实例对象上

      操作实例对象的某个属性时,会先在实例对象上找这个属性,若是找不到,则会沿着原型链去找

        FU.prototype.a = 111
        let f = new FU()
        console.log(f) //FU {}
        console.log(f.a) //111
        console.log(FU.prototype.a)  //111
    
        f.a = 222
        console.log(f) //FU {a: 222}
        console.log(f.a) //222
        console.log(FU.prototype.a)  //111
    
        FU.prototype.a = 333
        console.log(f) //FU {a: 222}
        console.log(f.a) //222
        console.log(FU.prototype.a)  //333
  • 相关阅读:
    lua for循环
    多面体的欧拉公式
    流形(Manifold)初步
    Laplace算子和Laplacian矩阵
    多重网格方法(Multigridmethod)
    多重网格方法
    谷歌浏览器兼容IE插件
    伽辽金法
    共轭梯度法
    有限元分析
  • 原文地址:https://www.cnblogs.com/jthr/p/16602796.html
Copyright © 2020-2023  润新知