Prototype

作者: xiao_A | 来源:发表于2016-02-21 21:50 被阅读551次

    Prototype是js面向对象中实现多态的核心,或者说是区别于普通面向对象语言如java等的灵魂所在,越是这种玩意,越是坑,因为如果对这些理解不深,反而会被它的一些表面现象所迷惑,导致各种深层bug,不断入坑。
    这里对自己之前所做的项目中所用到的此部分内容做一些总结

    思考

    开篇我想就我之前用JS的一些体会,简单说几个点

    • 人们常说,JS中万物皆对象,所以很多时候如果我们用Java等语言的(类-对象)逻辑去套JS反而会让自己无法理解。
      这里,我们需要破而后立,先树立一个概念,JS万物皆对象,记住是对象,不是类!即使我们会定义一些function,然后使用new去定义初始化一些对象,但是这里的function仍然是对象,只是刚好能够用来帮助初始化一类对象而已

    JS中的对象

    通常来说,javascript中的对象就是一个指向prototype的指针和一个自身的属性列表。javascript创建对象时采用了写时复制的理念。
    只有 构造器 才具有prototype属性,原型链继承就是创建一个新的指针,指向构造器的prototype属性。
    prototype属性之所以特别,是因为javascript时读取属性时的遍历机制决定的。本质上它就是一个普通的指针。
    构造器包括以下对象:

    1. Object
    2. Function
    3. Array
    4. Date
    5. String

    Prototype

    Prototype是啥

    这里强烈推荐参考[关于JS中的constructor与prototype][],这应该是全网写的最直白的,帮助我们小白看懂其中的逻辑
    首先,prototype我的理解是一个对象的属性,根据上文,我们知道只有构造器才有prototype属性。
    prototype属性又指向了一个prototype对象,注意prototype属性与prototype对象是两个不同的东西,要注意区别。在prototype对象中又有一个constructor属性,这个constructor属性同样指向一个constructor对象,而这个constructor对象恰恰就是这个function函数本身。
    看图(本文图均出自[关于JS中的constructor与prototype][]文章,下文不再说明)


    prototype和构造器

    Sample Code:

    function Person(name)
    {
       this.name=name;
       this.showMe=function() {
                 alert(this.name);
       }
    };
    var one=new Person('js');
    alert(one.prototype)//undefined
    alert(typeof Person.prototype);//object
    alert(Person.prototype.constructor);//function Person(name) {...};
    

    分析:
    其中one是具体的构造器弄出来的对象,所以没有prototype属性。而Function有(Function是构造器),并且prototype中有只想具体构造函数的属性

    JS中对象的定义过程

    按照《悟透javascript》书中说的,new形式创建对象的过程实际上可以分为三步:
    第一步是建立一个新对象(叫A吧);
    第二步将该对象(A)内置的原型对象设置为构造函数(就是Person)prototype 属性引用的那个原型对象;
    第三步就是将该对象(A)作为this 参数调用构造函数(就是Person),完成成员设置等初始化工作。
    其中第二步中出现了一个新名词就是内置的原型对象,注意这个新名词跟prototype对象不是一回事,为了区别我叫它inobj,inobj就指向了函数Person的prototype对象。在person的prototype对象中出现的任何属性或者函数都可以在one对象中直接使用,这个就是javascript中的原型继承了。


    对象与Prototype

    这样one对象通过内置的原型对象inobj就可以直接访问Person的prototype对象中的任何属性与方法了。这也就解释了上面的代码中为什么one可以访问form函数了。因为prototype对象中有一个constructor属性,那么one也可以直接访问constructor属性。

    JS继承(原型链)

    继承的实现很简单,只需要把子类的prototype设置为父类的一个对象即可。注意这里说的可是对象哦!
    那么通过prototype属性实现继承的原理是什么呢?还是先看图形说明,然后编写代码进行验证。


    继承(原型链)

    Sample Code:

    function Person(name) {
       this.name=name;
       this.showMe=function() {
           alert(this.name);
       }
    };
    Person.prototype.from=function() {
      alert('I come from prototype.');
    }
    function SubPerson() {
    }
    SubPerson.prototype=new Person();
    var subOne=new SubPerson();
    subOne.from();//I come from prototype.
    alert(subOne.constructor);//function Person(name) {...};
    alert(SubPerson.prototype.constructor);//function Person(name) {...};
    

    这个所谓的原型链就是从最下方的子对象开始,往自己的原型上溯。找调用的属性或者方法,如果找不到就继续找原型的原型。一直下去。这个比较好理解,和普通的父类回溯是差不多的逻辑。

    What's More

    至此,prototype的大概应该有所理解了。那么还有几个非常重要的细节,并且是使用最多的特性需要再强调一下,其实已经隐藏在上面的code里了。

    1. 每一个对象(被构造器创造出来的对象)姑且成为myObj,即new+某个function弄出的对象,可以直接访问constructor属性,这玩意指向的就是构造器
      但是同时,这玩意是没有prototype属性的,因为prototype只在构造器里才有。不过我们可以这样找到他的prototype,那就是myObj. constructor. prototype
    2. 函数对象中自身声明的方法和属性与prototype声明的对象有什么差别?
      有下面几个差别:
    • 自身声明的方法和属性是 静态的, 也就是说你在声明后,试图再去增加新的方法或者修改已有的方法,并不会 对由其已经创建的对象产生影响
    • 而prototype可以动态地增加新的方法或者修改已有的方法, 从而是 动态的 ,一旦 父函数对象 声明了相关 的prototype属性,由其创建的对象会 自动继承 这些prototype的属性.

    总结下,结合上文开头所述,prototype是指针,指向的是一个prototype对象。而具体的调用在在具体使用的时候,才去根据原型链一个一个去找的。所以在你update了prototype的属性和方法后,所有继承了这个prototype的对象都能动态的自动继承这些新update的玩意。这个才是JS作为动态的面向对象语言最有价值的玩意

    Javascript的方法

    JS中有三类方法

    a. 类方法
    b. 对象方法
    c. 原型方法

    Sample Code:

    function People(name) {
     this.name=name;
     //对象方法
     this.Introduce=function(){
       alert("My name is "+this.name);
      } 
    }
    //类方法
    People.Run=function(){
      alert("I can run");
    }
    //原型方法
    People.prototype.IntroduceChinese=function(){
      alert("我的名字是"+this.name);
    }
    

    参考文章
    [JS中的prototype][]
    [关于JS中的constructor与prototype][]
    [javascript必知必会之prototype][]
    [JS中的prototype]:http://www.cnblogs.com/yjf512/archive/2011/06/03/2071914.html
    [关于JS中的constructor与prototype]:http://blog.csdn.net/niuyongjie/article/details/4810835
    [javascript必知必会之prototype]:http://www.cnblogs.com/mindsbook/archive/2009/09/19/javascriptYouMustKnowPrototype.html

    相关文章

      网友评论

          本文标题:Prototype

          本文链接:https://www.haomeiwen.com/subject/dztbkttx.html