zoukankan      html  css  js  c++  java
  • 快速了解面向对象编程的一些概念

    1.原型 prototype

    JavaScript的每个对象都继承另一个对象(“原型”(prototype)对象)。我们要记住,每一个对象(null除外)都有原型对象,无论是通过那种方式创建的对象。

    1).如果对象是通过对象直接量创建的。

    var o={};

    那么我们可以通过Object.prototype获得对原型对象的引用

    2).如果对象是通过关键字new和构造函数创建的话。

    对象的原型对象就是构造函数的prototype值

    function Animal(){
    
    }
    var pig=new Animal();
    pig对象的原型对象就是Animal.prototype
    

    3).如果对象是通过new Object()创建的,那么原型对象就是Object.prototype

    总结:当调用构造函数创建了一个新实例后,该实例的内部将包含一个指针(内部属性prototype),指向构造函数的原型对象。我们始终要明确,这个连接是存在于实例对象与构造函数的原型对象之间,而不是存在于实例与构造函数之间。

    2.constructor属性

    默认情况下,所有原型对象都会自动获得一个constructor(构造函数)属性,而通过这个构造函数,我们还可继续为原型对象添加其他属性和方法。prototype对象有一个constructor属性,默认指向prototype对象所在的构造函数。由于constructor属性定义在prototype对象上面,意味着可以被所有实例对象继承。

    function P() {}
    P.prototype.constructor === P // true
    
    var p = new P();
    p.constructor // function P() {}
    p.constructor === P.prototype.constructor // true
    p.hasOwnProperty('constructor') // false
    

    constructor属性的作用,是分辨原型对象到底属于哪个构造函数。

    由于constructor属性是一种原型对象与构造函数的关联关系,所以修改原型对象的时候,务必要小心。

    实例

    function A() {}
    var a = new A();
    a instanceof A // true
    
    function B() {}
    A.prototype = B.prototype;
    a instanceof A // false
    

    上面代码中,a是A的实例。修改了A.prototype以后,constructor属性的指向就变了,导致instanceof运算符失真。

    所以,修改原型对象时,一般要同时校正constructor属性的指向。

    实例

    Cat.prototype = new Animal();//赋予一个新值,它相当于完全删除了prototype 对象原先的值,包括原型对象所指的构造函数
    
    Cat.prototype.constructor = Cat;//任何一个prototype对象都有一个constructor属性,指向它的构造函数,将原型对象的构造函数改回Cat。
    

    如果替换了prototype对象,

      o.prototype = {};
    

    那么,下一步必然是为新的prototype对象加上constructor属性,并将这个属性指回原来的构造函数。

      o.prototype.constructor = o;
    

    3.原型链

    var arr=new Array();
    

    新创建了一个arr对象,它的原型对象是Array.prototype,那么Array.prototype的原型对象是什么了?答案是Object.prototype,即Object构造函数的prototype属性指向的那个对象,那么Object.prototype有原型对象吗?有,是null(Object.getPrototypeOf(Object.prototype)结果返回none),原型追溯到这里也就终止了。

    所以所有对象如果一层层地往上上追溯,所有对象的原型最终都可以上溯到Object.prototype,这样就形成了一条原型链了。

    4.继承

    对象的属性和方法,有可能是定义在自身,也有可能是从定义在它的原型对象那继承而来的。为了更好理解继承,我们需要了解属性访问的细节。

    假设我们要查询对象o的属性x,如果o中没有x,那么将会继续在o的原型对象中查询属性x,如果这个原型对象也没有x,那么就继续在这个原型对象的原型中找,直到找到x或者找到原型对象是null为止。我们可以看到,在找属性x时,对象的原型属性构成了一个链,通过这个链就可以实现属性的继承。

    实例

    var o={};
    o.x=1;//自定义属性x
    var p=inherit(o);//p继承o和Object.prototype
    p.y=2;//自定义一个属性y
    var q=inherit(p);//q继承p,o和Object.prototype
    p.z=3;//自定义一个属性z
    var s=q.toString();//q.toString()继承自Object.prototype
    q.x+q.y//结果为3,x和y分别继承o和p
    

    只有在查询属性时,才会体会到继承的存在。如果o中已经有x属性了,那么这个属性就不是继承而来的,无论它的原型对象是不是也有x属性,如果原型对象也有x属性,那么o中的x属性就相当于重写了x(对象自身和它的原型,都定义了一个同名属性,那么优先读取对象自身的属性,这叫做“覆盖”(overiding)。,否则就是自定义属性了。

  • 相关阅读:
    neo4j︱与python结合的py2neo使用教程
    Neo4j 简介 2019
    110.Java对象的序列化
    109.Java序列流
    108.Java装饰器设计模式
    107.Java中IO流_字符流的缓冲区
    106.Java中IO流_字符流的异常处理
    105.Java中IO流_字符流拷贝文件
    104.Java中IO流_字符流_Writer
    103.Java中IO流_字符流_Reader
  • 原文地址:https://www.cnblogs.com/YeChing/p/6284589.html
Copyright © 2011-2022 走看看