zoukankan      html  css  js  c++  java
  • 摘的一段关于原型的介绍

    在典型的面向对象的语言中,如java,都存在类(class)的概念,类就是对象的模板,对象就是类的实例。但是在Javascript语言体系中,是不存在类(Class)的概念的,javascript中不是基于‘类的',而是通过构造函数(constructor)和原型链(prototype chains)实现的。但是在ES6中提供了更接近传统语言的写法,引入了Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。基本上,ES6的class可以看作只是一个语法糖,它的绝大部分功能,ES5都可以做到,新的class写法只是让原型对象的写法更加清晰、更像面向对象编程的语法而已。

    1.构造函数的简单介绍

      在我的一篇Javascript 中构造函数与new命令的密切关系文章中,详细了介绍了构造函数的概念和特点,new命令的原理和用法等,如果对于构造函数不熟悉的同学,可以前往细细品味。以下做一个简单的回顾。

      所谓构造函数,就是提供了一个生成对象的模板并描述对象的基本结构的函数。一个构造函数,可以生成多个对象,每个对象都有相同的结构。总的来说,构造函数就是对象的模板,对象就是构造函数的实例。

      构造函数的特点有:

        a:构造函数的函数名首字母必须大写。

        b:内部使用this对象,来指向将要生成的对象实例。

        c:使用new操作符来调用构造函数,并返回对象实例。

      看一个最简单的一个例子。

    1

    2

    3

    4

    5

    function Person(){

     this.name = 'keith';

    }

     var boy = new Person();

    console.log(boy.name); //'keith'

    2.构造函数的缺点

      所有的实例对象都可以继承构造函数中的属性和方法。但是,同一个对象实例之间,无法共享属性。

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    function Person(name,height){

     this.name=name;

     this.height=height;

     this.hobby=function(){

     return 'watching movies';

    }

     }

    var boy=new Person('keith',180);

     var girl=new Person('rascal',153);

     console.log(boy.name); //'keith'

     console.log(girl.name); //'rascal'

     console.log(boy.hobby===girl.hobby); //false

     上面代码中,一个构造函数Person生成了两个对象实例boy和girl,并且有两个属性和一个方法。但是,它们的hobby方法是不一样的。也就是说,每当你使用new来调用构造函数放回一个对象实例的时候,都会创建一个hobby方法。这既没有必要,又浪费资源,因为所有hobby方法都是童颜的行为,完全可以被两个对象实例共享。

      所以,构造函数的缺点就是:同一个构造函数的对象实例之间无法共享属性或方法。

    3.prototype属性的作用

      为了解决构造函数的对象实例之间无法共享属性的缺点,js提供了prototype属性。

      js中每个数据类型都是对象(除了null和undefined),而每个对象都继承自另外一个对象,后者称为“原型”(prototype)对象,只有null除外,它没有自己的原型对象。

      原型对象上的所有属性和方法,都会被对象实例所共享。

      通过构造函数生成对象实例时,会将对象实例的原型指向构造函数的prototype属性。每一个构造函数都有一个prototype属性,这个属性就是对象实例的原型对象。

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    function Person(name,height){

    this.name=name;

    this.height=height;

    }

    Person.prototype.hobby=function(){

    return 'watching movies';

    }

    var boy=new Person('keith',180);

    var girl=new Person('rascal',153);

    console.log(boy.name); //'keith'

    console.log(girl.name); //'rascal'

    console.log(boy.hobby===girl.hobby); //true

      上面代码中,如果将hobby方法放在原型对象上,那么两个实例对象都共享着同一个方法。我希望大家都能理解的是,对于构造函数来说,prototype是作为构造函数的属性;对于对象实例来说,prototype是对象实例的原型对象。所以prototype即是属性,又是对象。

      原型对象的属性不是对象实例的属性。对象实例的属性是继承自构造函数定义的属性,因为构造函数内部有一个this关键字来指向将要生成的对象实例。对象实例的属性,其实就是构造函数内部定义的属性。只要修改原型对象上的属性和方法,变动就会立刻体现在所有对象实例上。

    1

    2

    3

    4

    5

    6

    Person.prototype.hobby=function(){

     return 'swimming';

     }

     console.log(boy.hobby===girl.hobby); //true

     console.log(boy.hobby()); //'swimming'

    console.log(girl.hobby()); //'swimming'

      上面代码中,当修改了原型对象的hobby方法之后,两个对象实例都发生了变化。这是因为对象实例其实是没有hobby方法,都是读取原型对象的hobby方法。也就是说,当某个对象实例没有该属性和方法时,就会到原型对象上去查找。如果实例对象自身有某个属性或方法,就不会去原型对象上查找。

    1

    2

    3

    4

    5

    boy.hobby=function(){

     return 'play basketball';

     }

     console.log(boy.hobby()); //'play basketball'

     console.log(girl.hobby()); //'swimming'

      上面代码中,boy对象实例的hobby方法修改时,就不会在继承原型对象上的hobby方法了。不过girl仍然会继承原型对象的方法。

      总结一下:

    a:原型对象的作用,就是定义所有对象实例所共享的属性和方法。

    b:prototype,对于构造函数来说,它是一个属性;对于对象实例来说,它是一个原型对象。

  • 相关阅读:
    块级标签与预格式化文本标签----------大多数XHTML可以表示为两种类型的标签:块标签(block tag)和内联标签(inline tag)
    下拉框与下拉框之间的联动效果
    下拉框与文本框之间的转换
    设置密码是否为可见
    html表单
    HTML基础2——综合案例3——创建考试报名表格
    HTML基础2——综合案例2——复杂的嵌套列表
    java配置、IntelliJ IDEA Ultimate激活、
    字节流转字符流OutputStreamWriter、InputStreamReader,关闭流的方法
    文件字节流、字符流、缓冲字节流、缓冲字符流、数据流
  • 原文地址:https://www.cnblogs.com/zhaiyf/p/7519791.html
Copyright © 2011-2022 走看看