zoukankan      html  css  js  c++  java
  • javascript之原型

    一、初识原型

          JS的引用类型会内置一个特殊的属性prototype。默认的prototype是object类型的,是引用类型。既然默认的prototype是object类型的,那么prototype也会有一个原型,并且指向object的原型。

    另外补充一点,function的原型可直接访问,object的不行。

    示例:

    function SuperType(){};
    
    SuperType.age=18;
    
    SuperType.prototype.color=[“red”,”blue”];
    
    var t1=new SuperType ();
    
    t1.name=”hh”;
    
    var t2=new SuperType ();
    
    t2.qq=”aa”;

    SuperType,t1,t2原型关系示意图:

    定义function SuperType时,编译器会为其分配一个prototype属性,并在内存中开辟一片区域用于存放SuperType的原型的数据,假设这片区域的地址为0xA。然后让SuperType的prototype指向0xA。由SuperType创建出来的t1和t2的prototype也指向内存地址0xA。如果有SuperType.prototype.color.push(“green”),则t1和t2的color也会变为[“red”,”blue”,”green”]。因为SuperType,t1,t2的原型指向的是同一个地址的数据。这个过程可以这么比喻:把原型比喻为你的银行卡账户,假设有一万块钱。当有人盗刷你的银行卡,刷走了4000,然后你去银行查看你账户余额,当然的会剩下6000。因为你跟盗刷你银行卡的人所持的银行卡指向的是同一个账户。

        SuperType.prototype.color.push(“green”)后,示意图如下:

    二、 原型链

    其实在上面的示意图中,顺着箭头走,如Test—>Test的原型—>Object的原型,就是一条原型链了。当然t2—>Test的原型—>Object的原型也是一条原型链。下面对原形链进行补充,说明原型链在继承体系中是怎么工作的。

    示例:

    function SuperType(){};
    SuperType.age=18;
    SuperType.prototype.color=[“red”,”blue”];
    
    function SubType(){}
    SubType.property=”property”;
    SubType.prototype=new SuperType();
    SubType.prototype.test=function(){alert(“test”);}
    
    function Child(){}
    Child.prototype=new SubType();
    var t1=new SuperType ();
    t1.name=”hh”;
    var t2=new SuperType ();
    t2.qq=”aa”;
    
    var s=new SubType();
    var c=new Child();

    注意,SubType的原型被重新赋值了,SubType.prototype=new SuperType();

    所以SubType的原型是SuperType的一个对象实例。

    上述代码的原型链示意图如下:

    三、重置原型

    要重置原型,只要对原型重新赋值即可。例如:function Person(){} Person.prototype={ name:”Leo” } 需要注意的是,Person原型重写后,Person的原型为{ name:”Leo”}。{ name:”Leo”}是一个匿名的Object实例,所以其constructor,为Object。也就是说重写后Person的原型的constructor为Object。如果constructor重要,可以为其增加一个constructor属性,如下:Person.prototype={          name:”Leo”,          constructor:Person}不过此时还会有一个问题,这样设置的constructor将会使constructor变成是可枚举的。所以,如果想让它变为不可枚举的,可用Object.defineProperty进行设置。

    四、原型的动态性

    示例:

    function Person(){}
    
    var p=new Person();
    
    Person.prototype.sayHi=function(){alert(“Hi”);};
    
    p.sayHi();//这里没问题,因为p在调用sayHi时,会先从自身找sayHi,找不到则会沿//着原形链去寻找,然后在Person的原型中找到了sayHi,于是就执行

    原型动态性之-------重写原型的问题

    function Person(){}
    
    var p=new Person();
    
    Person.prototype={
    
    sayName: function(){alert(“Hi”);},
    
    constructor:Person
    
    }
    
    p.sayName();//此时将会报错,p没有sayName方法

    这里为何p.sayName会报错,Person的原型不是有sayName么?

    且看下面的示意图:

    五、原型共享所引发的问题

    原型的优点就是共享。例如:

    function Person (){}
    Person.prototype.sayName=function(){};
    var p1=new Person ();
    var p2=new Person ();

    在原型中定义sayName函数,于是p1,p2对象有同一个sayName。而不会在内存中分配两次内存来分别存放p1的sayName和p2的sayName。而缺点也是由共享所致。共享对于函数而言,是合适的,但是对于其他属性而言,可能就会出问题。示例如下:

    function Person(){}
    Person.prototype.color=[“red”,”green”];
    var p1=new Person();
    var p2=new Person();
    alert(p1.color);//输出red,green
    alert(p2.color); //输出red,green
    p2.color.push(“blue”);
    alert(p1.color); //输出red,green,blue。

    注意,这里我并没有更改p1的color;alert(p2.color); //输出red,green,blue这里我们可以发现,p2的color进行更改之后,p1的color也跟着更改,这正是原型共享所引发的问题。

    六、原型链与instanceof实现原理

    假设a instanceof b,那么会从a的原形链中找出是否有跟b的原型相等的原型,如果找到则返回true,否则返回false。

    示例如下:

    function SuperType(){}
    function SubType(){}
    function Test(){}
    SubType.prototype=new SuperType();
    var s=new SubType();
    console.log(s instanceof SubType);//打出true,这是因为s的原型等于SubType的原型
    SubType.prototype=new SuperType();
    console.log(s instanceof SubType);//打出false

    示意图如下:(省略了百度上的文字说明而改为图片说明)

    以上是百度经验里关于 javascript原型 的介绍。

    延伸:

    1.构造函数中的return

    构造函数在没有return的情况下新的实例默认返回undefined;如果构造函数中有return语句,

    分两种情况:

    • return 基本类型,返回函数
    • return 对象,返回对象。

    2.原型模式的执行流程

    • 先查找构造函数实例里的属性或方法,如果有,就立即返回。
    • 如果构造函数的实例没有,就去它的原型对象里找,如果有,就立即返回

     拜读了风雨后见彩虹的文章

  • 相关阅读:
    windbg条件断点总结
    使用openssl命令剖析RSA私钥文件格式
    RSA读取密钥——使用openssl编程
    OPENSSL中RSA私钥文件(PEM格式)解析【一】
    电商系统架构——系统鸟瞰图
    构建高并发高可用的电商平台架构实践
    一些PHP性能的优化
    CentOS的Gearman安装
    php安装gearman扩展实现异步分步式任务
    使用 Gearman 实现分布式处理
  • 原文地址:https://www.cnblogs.com/Merrys/p/8012661.html
Copyright © 2011-2022 走看看