zoukankan      html  css  js  c++  java
  • javascript 权威指南(09)

    9.3.5. js通过相关的prototype混合编程进行类的支持

    function Circle(radius) {
        this.r = radius;//共有变量
        this.getR=function(){return radius;}//私有变量的相关实现,是通过闭包实现的。
                                            //私有函数是通过嵌套函数实现的,只能在函数体内通过this的方法定义,进行调用
    }
    Circle.PI = 3.14159;//类共有静态的属性
    Circle.max = function(a,b) { if (a.r > b.r) return a; else return b;};//类共有静态的方法
    Circle.prototype.area = function( ) { return Circle.PI * this.r * this.r; }//每个实例共有的方法,这个比类函数中定义this方法减少该句的执行次数。
    

    9.5. 类继承的相关代码,这相关的代码可见

    该实现和一般的继承存在差异,父类对于子类的同名属性其实是不存在的,或者相关的值是undefine,因为原型链继承的时候是通过一个空实例的。

    function Rectangle(w, h) {
        this.width = w;
        this.height = h;
    }
    Rectangle.prototype.area = function( ) { return this.width * this.height; }
    function PositionedRectangle(x, y, w, h) {
        Rectangle.call(this, w, h);//这个只是方法的调用,只是Rectangle函数里面涉及this的属性进行赋值
                                   //相关的prototype创建操作其实是要通过new操作符实现的,new 是先执行函数,在对函数的prototype属性,对该实例的相关的原型链进行创建
        this.x = x;
        this.y = y;
    }
    PositionedRectangle.prototype = new Rectangle( );//原型属性也是一个实例,继承则是使他成为父类的一个实例
    //上句中PositionedRectangle.prototype为一个Rectangle对象,所以PositionedRectangle.prototype中的属性是多余的,我们一般是继承方法
    delete PositionedRectangle.prototype.width;
    delete PositionedRectangle.prototype.height;
    //constructor属性指向的是创建函数,根据原型链现在指向额是Rectangle,所以需要重新定位
    PositionedRectangle.prototype.constructor = PositionedRectangle;
    PositionedRectangle.prototype.contains = function(x,y) {
        return (x > this.x && x < this.x + this.width &&
                y > this.y && y < this.y + this.height);
    }
    

    个人总结,可能有误:

    m.1. new操作符的作用,就是创建对象,没有new的是返回的是函数的返回值

    function Circle(radius) {
        this.r = radius;
    }
    var a= Circle(12);//a访问不到area属性,a只是Circle函数的返回值,只是一个undefined;
    var b = new Circle(12);//b可访问area属性
    

    m.2. new操作符的执行顺序 new 是先进行原型链的组成,再执行函数

    function class1(){};
    function class2(){};
    function class3()
    {
    class3.prototype=new class2();
    };
    class3.prototype=new class1();
    var obj=new class3();
    alert(obj instanceof class3);//false
    alert(obj instanceof class2);//false
    alert(obj instanceof class1);//true
    var obj2=new class3();
    alert(obj2 instanceof class3);//false
    alert(obj2 instanceof class2);//true
    alert(obj2 instanceof class1);//false
    var obj3=new class3();
    alert(obj3 instanceof class3);//true
    alert(obj3 instanceof class2);//true
    alert(obj3 instanceof class1);//false
    

    m.3. 原型链的相关的概念

    原型链的建立其实是在对象创建的时候就建立的,在创建对象以后,修改原型链的方向,原来的对象是不受影响的,下面是引用博文

    在javascript里,每个function都有一个prototype属性,这个属性的用途是实现继承机制。必如下面定义的function class1:

    function class1(){} class1.prototype = {a:10,b:100};则class1的每个实例都会从prototype继承a和b这两个属性。

    同时,每个对象都会有一个内部的属性_proto_(不同的javascript虚拟机实现用的名字可能不同),这个属性对js开发人员不可见,只在虚拟机内部使用。

    每当创建一个对象的时候,这个对象的_proto_就会被赋值为这

    个对象的构造函数的 prototype,这样对象的_proto_属性和构造函数的prototype引用相同的对象,并且一旦对象创建完成,_proto_属性就不会改变。

    这样通过对象的_proto_属性,以及_proto_所引用的对象的_proto_属性,就构成了一个_proto_链。 当访问一个对象的属性和方法的时候,js虚拟机正是通过这个_proto_链来查找的。

    关于instanceof:

    假设有一条这样的语句:o instanceof c;

    在上面的语句执行过程中,虚拟机会把c.prototype和o的_proto_链上的节点逐个进行比较,如果找到相等的节点,则返回true,否则返回 false。

    function class1(){};
    function class2(){};
    class2.prototype=new class1();
    function class3(){};
    class3.prototype=new class2();
    function class4(){};
    var obj=new class3();
    alert(obj instanceof class3);//true
    alert(obj instanceof class2);//true
    alert(obj instanceof class1);//true
    但是有想过解释器是如何判断一个对象是否是一个类的实例吗?网上大多是说通过原型链来判断。上面可能看到有一个类class4没被用到过,那在后面添上这句
    class2.prototype=new class4();
    alert(obj instanceof class3);//true;
    alert(obj instanceof class2);//false;_proto_属性已经存在了,所以class2非原来的class2了
    alert(obj instanceof class1);//true;
    

    m.4. 一直有这个概念,原型链的查找,最后是有一个null值结束的。

    原来我一直以为是Object.prototype.constructor.prototype指向了null,这是错的,Object.prototype.constructor是一个Prototype函数,它的prototype也是一个Object的实例,

    根据Object.prototype.constructor.prototype===Object.prototype,我现在可以理解new操作的时候通过相应的判断,把最后的_proto_属性设置成了null

    m.5.上文提到的一个在继承中实现的和其他语言的不同 (失败)

    该实现和一般的继承存在差异,父类对于子类的同名属性其实是不存在的,或者相关的值是undefine,因为原型链继承的时候是通过一个空实例的。

    function Rectangle(w, h) {
        this.width = w;
        this.height = h;
    }
    Rectangle.prototype.area = function( ) { return this.width * this.height; }
    PositionedRectangle.super=Rectangle;
    function PositionedRectangle(x, y, w, h) {
        this.x = x;
        this.y = y;
        PositionedRectangle.prototype= new PositionedRectangle.super(w,h);//拥有滞后性,因为先进行有原型链,在执行函数的,而且违背了原型链存在的初衷,方法的共享
        PositionedRectangle.prototype.constructor = PositionedRectangle;
    }
    PositionedRectangle.prototype.contains = function(x,y) {
        return (x > this.x && x < this.x + this.width &&
                y > this.y && y < this.y + this.height);
    }
    
  • 相关阅读:
    9.经典进程同步问题
    8.信号量
    7.进程同步之临界区问题
    6.CPU调度
    AIX 10G HA RAC卸载
    HP11.31安装11.2.0.3实施手册
    AIX上安装oracle10g
    习水医院12C RAC 数据库安装文档
    linux 11201(11203) ASM RAC 安装
    如果一个节点重新安装了,处理办法
  • 原文地址:https://www.cnblogs.com/legu/p/1703115.html
Copyright © 2011-2022 走看看