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);
}
原文地址:https://www.cnblogs.com/legu/p/1703115.html