zoukankan      html  css  js  c++  java
  • js高级——构造函数,实例对象和原型对象——prototype、__proto__和constructor构造器

    一、前言

      了解JavaScript面向对象,需要先了解三个名词: 构造函数,实例对象和原型对象

      注意:JavaScript中没有类(class)的概念,取而代之的是构造函数,两者类似却又有很大的差别。

      先上代码,最常用的:

    function Person(name, age) {
     this.name = name;
     this.age = age;
     this.eat= function() { alert('吃西红柿') } 
    }
    var person1 = new Person('小米', 28);
    var person2 = new Person('大米', 23);

      Chrome打印测试,上图:

    上图分别是:

    • 图一打印perspn1实例对象,
    • 图二打印Person构造函数,
    • 图三打印构造函数的prototype(即Person的原型对象)和person1的__proto__

       

      通过上面的打印,我们可以发现几个问题:

    1. 实例对象和构造函数一点也不像,
    2. person1.__proto__和Person.prototype一模一样

      我们先来看看第一个问题:实例对象和它的构造函数——打印出来的内容一点也不像

       

      这个问题就大了呀!

       我们都知道,在java中,类和它的实例对象之间有很紧密的关系,你的(属性和方法)是我的,我的还是我的!

      可是到了js这里,Person构造函数中并没有体现出他本该有的属性和方法

      也就是说,无论我们实例化出来多少个person,他们的属性和方法都是不一样的。属性不一样还可以理解,方法不一样就意味着:每个实例出来的person的方法并不是共用的(并不指向同一个地址空间),那我们要构造函数还有什么意义?

      我们要的还是类和实例对象的关系那样,能够共享数据,节省内存空间

     

      这就引出了我们今天要讲的关键:原型

     

    二、正文

    (一)、使用原型对象造共用属性和方法

      前面已经讲到,js的构造函数和实例对象之间,并不能够实现共享数据,节省内存空间的作用,所以我们就引入了原型这一概念

      再上代码:这次我们添加了原型方法play()

    //构造函数
    function Person(name, age) {
     this.name = name;
     this.age = age;
     this.eat= function() { alert('吃西红柿') } 
    }
    //添加原型方法
    Person.prototype.play = function() { alert("玩溜溜球")}
    //实例化对象
    var person1 = new Person('小米', 28);
    var person2 = new Person('大米', 23);

      在仅限Chrome测试:

    上图分别是:

    • 图一打印perspn1实例对象,
    • 图二打印Person构造函数,
    • 图三打印构造函数的prototype(即Person的原型对象)和person1的__proto__

      

      通过上图可以知道:构造函数中定义的方法,实例化后并不一样,而原型对象prototype中定义的方法确实相等的(指向同一地址)

      添加了原型方法后,实例对象person1和构造函数Person上并没有直观体现,反而在Person.prototype和person1.__proto__中显示了出来

         由此,我们可以知道,JS中给同一构造函数的实例对象 添加共用属性和方法,需要使用prototype这一属性,也就是原型对象来实现

       

    (二)、prototype和__proto__和constructor构造器

    上图表现出:Person.prototype === person1.__proto__

    即:实例对象的__proto__和构造函数的prototype相等(指向同一地址),完全一样

    上图,图一打印Person.prototype;图二打印person1.__proto__;图三打印Person构造函数

    通过上面三张图,我们可以发现:Person.prototype.constructor和person1.__proto__.constructor以及Person一模一样

     

    上图表现出:Person.prototype.constructor === Person

     即:构造函数的原型对象(prototype)的构造器(constructor)指向该构造函数

      

    通过之前的打印和上图,我们可以发现,

    • 实例对象中都有__proto__属性,而构造函数中都有prototype属性,
    • prototype和__proto__都有构造器constructor,其实实例对象的__proto__和构造函数的prototype是一样的(Person.prototype === person1.__proto__
    • 构造函数的原型对象(prototype)的构造器(constructor)指向该构造函数(Person.prototype.constructor === Person

     

     (三)、使用原型的注意事项

      原型属性和方法统一定义时,需要定义构造器constructor,即将构造函数的原型对象中的构造器指向该构造函数,否则原型属性和方法定义失败

    //添加原型方法
    Person.prototype.job= "程序员"
    Person.prototype.address = "苏州" 
    Person.prototype.study= function() { alert("学JavaScript")}
    
    //可以这样定义吗?
    Person.prototype = {
        job:  "程序员",
        address: "苏州" ,
        study:  function() { alert("学JavaScript")}
    }
    
    //上面的原型对象定义出错,需要加上constructor--手动修改构造器的指向
    Person.prototype = {
        constructor: Person,
        job:  "程序员",
        address: "苏州" ,
        study:  function() { alert("学JavaScript")}
    }

      分别将两种添加原型属性和方法的方式打印看看:

    上图分别是:

    • 图一为错误示范,表示未手动修改构造器指向,结果打印显示Person.prototype丢失构造器constructor,被新添加的对象覆盖
    • 图二为正确示范,表示手动修改构造器指向,即加上constructor: Person,

       

     三、结束

      加油哦,最后来张图

  • 相关阅读:
    Linux编译安装中configure、make和make install各自的作用
    转载的 Linux下chkconfig命令详解
    MYSQL主从不同步延迟原理分析及解决方案(摘自http://www.jb51.net/article/41545.htm)
    mysql主从延迟(摘自http://www.linuxidc.com/Linux/2012-02/53995.htm)
    http://ninghao.net/video/1554不错的学习网址
    javascript 内置对象和方法
    javascript 函数
    javascript 基础
    css z-index
    css 透明度
  • 原文地址:https://www.cnblogs.com/nangezi/p/10182752.html
Copyright © 2011-2022 走看看