zoukankan      html  css  js  c++  java
  • 简单理解javascript的原型prototype

    原型和闭包是Js语言的难点,此文主要讲原型。

    每一个方法都有一个属性是 prototype
    每一个对象都有一个属性是 _proto_
    一旦定义了原型属性或原型方法,则所有通过该构造函数实例化出来的所有对象,都继承了这些原型属性和原型方法,这是通过内部的_proto_链来实现的。

    /* Js所有的函数都有一个prototype属性,这个属性引用了一个对象,即原型对象,也简称原型。这个函数包括构造函数和普通函数,我们讲的更多是构造函数的原型,但是也不能否定普通函数也有原型。
    每一个方法都有一个属性叫做原型(prototype)
    prototype的定义:不需要显式地声明一个prototype属性,因为在每一个构造函数中都有它的存在。 */

    譬如普通函数:
    function Test(){

    }
    console.log("exp1 : " + Test.prototype); //  [object Object]

    console.log("exp1 : " + Test.prototype instanceof Object) //true

    譬如构造函数,也即构造对象。首先了解下通过构造函数实例化对象的过程。

    function A(x){
      this.x=x;
    }
    var obj=new A(1);

    实例化obj对象有三步:

      1. 创建obj对象:obj=new Object();

      2. 将obj的内部__proto__指向构造他的函数A的prototype,obj.constructor.prototype与的内部_proto_是两码事,实例化对象时用的是_proto_,obj是没有prototype属性的,但是有内部的__proto__,通过__proto__来取得原型链上的原型属性和原型方法

      3.将obj作为this去调用构造函数A,从而设置成员(即对象属性和对象方法)并初始化

    一旦定义了原型属性或原型方法,则所有通过该构造函数实例化出来的所有对象,都继承了这些原型属性和原型方法,这是通过内部的_proto_链来实现的

    譬如: A.prototype.say=function(){alert("Hi")};

    那所有的A的对象都具有了say方法,这个原型对象的say方法是唯一的副本给大家共享的,而不是每一个对象都有关于say方法的一个副本

    以下通过几个实例来深入理解prototype:

    /* exp2:start...*/
    /*
    给prototype添加属性
    prototype是一个对象,因此,你能够给它添加属性。
    你添加给prototype的属性将会成为使用这个构造函数创建的对象的通用属性。 */
    function Fish(name, color){
      this.name = name;
      this.color = color;
    }
    Fish.prototype.livesIn = 'water';
    Fish.prototype.price = 20;

    //构造
    var fish1 = new Fish('mackarel', 'gray');
    var fish2 = new Fish('goldfish', 'orange');
    var fish3 = new Fish('salmon', 'white');

    for (var i = 1; i <= 3; i++){
      var fish = eval('fish' + i); // 取得指向这条鱼的指针
      console.log("exp2 : " + fish.name + ',' + fish.color + ',' + fish.livesIn + ',' + fish.price);
    }

    //mackarel,gray,water,20
    //goldfish,orange,water,20
    //salmon,white,water,20

    /* exp2:end...*/

    /* exp3:start...*/
    /* 当一个对象被创建时,这个构造函数将会把它的属性prototype赋给新对象的内部属性__proto__。这个__proto__被这个对象用来查找它的属性。 */
    function Employee(name, salary){
      this.name = name;
      this.salary = salary;
    }
    /* Employee的所有对象都具有getSalary()和addSalary()方法,此原型对象的这两个方法是是唯一的,也是共享的,
      并非Employee的所有对象都拥有此方法(非一一对应,而是多对一) */
    Employee.prototype.getSalary = function getSalaryFunction(){
      return this.salary;
    }
    Employee.prototype.addSalary = function addSalaryFunction(addition){
      return this.salary = this.salary + addition;
    }
    var boss1 = new Employee('Jon', 200000);
    var boss2 = new Employee('Kim', 100000);
    var boss3 = new Employee('Sam', 150000);

    console.log("exp3 : " + boss1.getSalary()); // 输出 200000
    console.log("exp3 : " + boss2.getSalary()); // 输出 100000
    console.log("exp3 : " + boss3.getSalary()); // 输出 150000

    console.log("exp3 : " + boss1.addSalary(5000)); // 输出 205000
    console.log("exp3 : " + boss2.addSalary(5000)); // 输出 105000
    console.log("exp3 : " + boss3.addSalary(5000)); // 输出 155000

    /* exp3:end...*/

    /* exp4:start...*/
    function F() {}
    var i = new F();
    console.log("exp4 : i.prototype : " + i.prototype + " , F.prototype : " + F.prototype ,", i.__proto__ : " + i.__proto__ + " , F.__proto__ : " + F. __proto__);
    //exp4 : i.prototype : undefined , F.prototype : [object Object] , i.__proto__ : [object Object] , F.__proto__ : function Empty() {}
    /* exp4:end...*/

  • 相关阅读:
    Android 创建Library Project(库项目)与引用操作
    Android插件化(二):使用DexClassLoader动态载入assets中的apk
    洛谷P3388 【模板】割点(割顶)(tarjan求割点)
    BZOJ 1179: [Apio2009]Atm(tarjan+SPFA)
    洛谷P1067 多项式输出(模拟)
    洛谷P2118 比例简化(暴力)
    BZOJ 3714: [PA2014]Kuglarz(最小生成树)
    BZOJ 4289: PA2012 Tax(最短路)
    BZOJ 4152: [AMPPZ2014]The Captain(最短路)
    洛谷P2939 [USACO09FEB]改造路Revamping Trails(最短路)
  • 原文地址:https://www.cnblogs.com/chenrunlin/p/4935478.html
Copyright © 2011-2022 走看看