javascript练习题(五)

本文围绕JavaScript的继承模式进行实战演练,通过实现多重继承,创建不同图形构造器如Triangle、Square、Rectangle等,并探讨了如何利用uber属性实现子对象访问父对象的方法,以及让父对象能够追踪其子对象。在解决问题的过程中,对原型继承和对象构造进行了深入思考。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第6章 继承

1.使用原型继承模式(而不是属性拷贝的方式)实现多重继承。例如:

var my = objectMulti(obj,another_obj,a_third,{
    additional: "properties"
});

属性additional应该是私有属性,而其他属性则应该归并如prototype。

答:我也不是很清楚作者什么意思,我就想出这么一个挫方法,以后有了更好的方法再改吧。

    function objectMulit() {
        var n={};
        var parent;
        var np={};
        var i=0;
        var l=arguments.length;
        for(i=0;i<l-1;i++){
            parent=arguments[i];
            for(var j in parent){
                if(parent.hasOwnProperty([j])){
                    np[j]=parent[j];
                }
            }
        }
        n.prototype=np;
        for(var j in arguments[l-1]){
            if(arguments[l-1].hasOwnProperty([j])){
                n[j]=arguments[l-1][j];
            }
        }
        return n;
    }

    var obj={
        attr1: "attr1"
    };
    var another_obj={
        attr2: "arrt2"
    };
    var a_third={
        attr3: "attr3"
    };
    var my=objectMulit(obj,another_obj,a_third,{
        additional:"properties"
    });
    console.log(my);

ps:原书标准答案

function objectMulti() {
     var Constr,
     i,
     prop,
     mixme;
     // constructor that sets own properties
     var Constr = function (props) {
         for (var prop in props) {
             this[prop] = props[prop];
         }
     };
     // mix into the prototype
     for (var i = 0; i < arguments.length - 1; i++) {
        var mixme = arguments[i];
        for (var prop in mixme) {
             Constr.prototype[prop] = mixme[prop];
        }
     }
     return new Constr(arguments[arguments.length - 1]);
}

2.利用上面(书中前文,代码如下)的画布示例展开实践,

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <style type="text/css">
        #canvas{
            background-color: #ccc;
        }
    </style>
</head>
<body>

<canvas id="canvas" width="1000px" height="1000px"></canvas>
<script type="text/javascript">
    function Point(x,y){
        this.x=x;
        this.y=y;
    }
    function Line(p1,p2){
        this.p1=p1;
        this.p2=p2;
        this.length=Math.sqrt(Math.pow(p1.x-p2.x,2)+Math.pow(p1.y-p2.y,2));
    }
    function Shape(){
        this.points=[];
        this.lines=[];
        this.init();
    }
    Shape.prototype={
        init:function(){
            if(this.context===undefined){
                var canvas=document.getElementById("canvas");
                Shape.prototype.context=canvas.getContext("2d");
            }
        },
        draw:function(){
             var i,ctx=this.context;
             ctx.strokeStyle=this.getColor();
             ctx.beginPath();
             ctx.moveTo(this.points[0].x,this.points[0].y);
             for(i=0;i<this.points.length;i++){
                ctx.lineTo(this.points[i].x,this.points[i].y);
             }
             ctx.closePath();
             ctx.stroke();
        },
        getColor:function(){
            var i,rgb=[];
            for(i=0;i<3;i++){
                rgb[i]=Math.round(255*Math.random());
            }
            return "rgb("+rgb.join(",")+")";
        },
        getLines:function(){
            if(this.lines.length>0){
                return this.lines;
            }
            var i,lines=[];
            for(i=0;i<this.points.length;i++){
                lines[i]=new Line(this.points[i],this.points[i+1]||this.points[0]);
            }
            this.lines=lines;
            return lines;
        },
        getArea:function(){},
        getPerimeter:function(){
            var i,perim=0,lines=this.getLines();
            for(i=0;i<lines.length;i++){
                perim+=lines[i].length;
            }
            return perim;
        }
    }
    function Triangle(a,b,c){
        this.points=[a,b,c];
        this.getArea=function(){
            var p=this.getPerimeter();
            var s=p/2;
            return Math.sqrt(s*(s-this.lines[0].length)*(s-this.lines[1].length)*(s-this.lines[2].length));
        };
    }
    function Rectangle(p,side_a,side_b){
        this.points=[
            p,
            new Point(p.x+side_a,p.y),
            new Point(p.x+side_a,p.y+side_b),
            new Point(p.x,p.y+side_b)
        ];
        this.getArea=function(){
            return side_b*side_a;
        };
    }
    function Square(p,side){
        Rectangle.call(this,p,side,side);
    }
    var s=new Shape();
    Triangle.prototype=s;
    Rectangle.prototype=s;
    Square.prototype=s;

    var p1=new Point(100,100);
    var p2=new Point(300,100);
    var p3=new Point(200,0);

    var t=new Triangle(p1,p2,p3);
    t.draw();
    console.log(t.getPerimeter());
    console.log(t.getArea());

    var r=new Rectangle(new Point(200,200),50,100);
    r.draw();
    console.log(r.getArea());
    console.log(r.getPerimeter());

    var s=new Square(new Point(130,130),50);
    s.draw();
    console.log(s.getArea());
    console.log(s.getPerimeter());

    new Square(p1,200).draw();
</script>
</body>
</html>

尝试各种不同的东西,例如:

1)绘制出一些Triangle、Square、Rectangle图形。
答:

new Rectangle(new Point(120,40),10,60).draw();

(我又画了一个小烟囱,好了,就这样吧。。。)

2)添加更多的图形构造器,例如Trapezoid、Rhombus、Kite以及Pentagon等。如果您还想对canvas标签有更多的了解,也可以创建一个Circle构造器,该构造器需要您重写父对象的draw()方法。
答:画出梯形、菱形、风筝什么的太麻烦了,我就做一个多边形的类,和一个圆形的。

    function Polygon(){
        this.points=arguments;
    }
    Polygon.prototype=s;

    var plg1=new Polygon(new Point(100,400),new Point(300,400),new Point(350,600),new Point(50,600));
    plg1.draw();
    var plg2=new Polygon(new Point(600,50),new Point(550,150),new Point(600,250),new Point(650,150));
    plg2.draw();

    function Circle(p1,radius){
        this.centerPoint=p1;
        this.radius=radius;
        this.draw=function(){
            var ctx=this.context;
            ctx.beginPath();
            ctx.strokeStyle=this.getColor();
            ctx.arc(this.centerPoint.x,this.centerPoint.y,this.radius,0,Math.PI*2,false);
            ctx.stroke();
        };
        this.getPerimeter=function(){
            return Math.PI*2*this.radius;
        };
        this.getArea=function(){
            return Math.pow(this.radius,2)*Math.PI;
        };
    }
    Circle.prototype=s;

    var c=new Circle(new Point(700,500),100);
    console.log(c.getPerimeter());
    console.log(c.getArea());
    console.log(c);
    c.draw();

3)考虑一下,是否还有其他方式可以实现并使用这些类型继承关系,从而解决上述问题?
答:书中前面内容随便找了个方式

    function extend(Child,stuff){
        var F=function(){};
        F.prototype=stuff;
        Child.prototype=new F();
        Child.prototype.constructor=Child;
        Child.uber=stuff;
    }

4)请选择一个子对象能通过uber属性访问的方法,并为其添加新的功能,使得父对象可以追踪到该对象所属的子对象。例如,或许我们可以在父对象中建立一个用于存储其所有子对象的数组属性。

答:想了半天不知道怎么弄,试了几种方法也不行。父对象怎么也追踪不到子对象啊。然后我就看了一下答案,把原书的标准答案给出来

function inherit(Child, Parent) {
     // remember prototype
     var extensions = Child.prototype;
     // inheritance with an intermediate F()
     var F = function () {};
     F.prototype = Parent.prototype;
     Child.prototype = new F();
     // reset constructor
     Child.prototype.constructor = Child;
     // remember parent
     Child.prototype.uber = Parent;
     // keep track of who inherits the Parent
     if (!Parent.children) {
         Parent.children = [];
     }
     Parent.children.push(Child);
     // carry over stuff previsouly added to the prototype
     // because the prototype is now overwritten completely
     for (var i in extensions) {
     if (extensions.hasOwnProperty(i)) {
         Child.prototype[i] = extensions[i];
         }
     }
}

父对象构造函数保留了子对象的构造函数,也不是保留对象啊。
我考虑到可能是翻译有误会,所以把英文版问题也贴出来吧

Think of another way to do the inheritance part. Use uber so kids can have access to their parents. Also, get parents to be aware of their children.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值