search

Home  >  Q&A  >  body text

javascript - A problem with js scope-safe constructors

function Polygon(sides){
                if(this instanceof Polygon){
                    this.sides=sides;
                    this.getArea=function(){
                        return 0;
                    }
                }else{
                    return new Polygon(sides);
                }
            }
            
            function  Rectangle(wifth,height){
                Polygon.call(this,2);
                this.width=this.width;
                this.height=height;
                this.getArea=function(){
                    return this.width * this.height;
                };
            }
            
            var rect=new Rectangle(5,10);
            alert(rect.sides); //undefined

This code is an example of P598-599 in JS Elevation 3
What I want to ask is why the alert is undefined?

phpcn_u1582phpcn_u15822854 days ago528

reply all(4)I'll reply

  • 曾经蜡笔没有小新

    曾经蜡笔没有小新2017-05-19 10:17:29

    Start

    var rect=new Rectangle(5,10);

    Enter Rectangle, this points to a new object, and call it object1

    Executed to

    Polygon.call(this,2);

    Enter Polygon in the name of object1

               function Polygon(sides){
                    if(this instanceof Polygon){
                        this.sides=sides;
                        this.getArea=function(){
                            return 0;
                        }
                    }else{
                        return new Polygon(sides);
                    }
                }
    The prototype of

    object1 is Rectangle, so go to else

    return new Polygon(sides);

    Enter Polygon again, this points to a new object, and call it object2

    The prototype of

    object2 is Polygon, so object2 is given sidesgetArea

    Return to object1's territory, Polygon.call(this,2);Return to object2, and then... Then throw it away.

                function  Rectangle(wifth,height){
                    Polygon.call(this,2);
                    this.width=this.width;
                    this.height=height;
                    this.getArea=function(){
                        return this.width * this.height;
                    };
                }

    Then give object1 undefinedwidthheightgetArea .

    Finally, rect got object1

    Add the solution and let Rectangle share the prototype of Polygon

    function Rectangle(wifth,height){
        Polygon.call(this,2);
        this.width=width;
        this.height=height;
        this.getArea=function(){
            return this.width * this.height;
        };
    }
    Rectangle.prototype = Polygon.prototype

    reply
    0
  • 淡淡烟草味

    淡淡烟草味2017-05-19 10:17:29

    In Rectangle, point Polygon's this to Rectangle's this. When Rectangle is used as a constructor, this refers to the instance of Rectangle, that is, rect in this example, and the prototype of Polygon is not on the prototype chain of rect, that is, this instanceof Polygon is false, so the return new Polygon(sides) in else is used, and sides is not attached to the instance, so the sides attribute does not exist on the rect instance.
    There is also Rectangle(with,height), width is written wrong

    reply
    0
  • 習慣沉默

    習慣沉默2017-05-19 10:17:29

    In your example, Polygon is an interference item and has no effect on Rectangle at all.

    Remove Polygon.call(this,2);Look again, can you understand the reason

    reply
    0
  • 巴扎黑

    巴扎黑2017-05-19 10:17:29

    • Print this and you will know the reason

    • this.sides=sides is hung on Polygon

    • return new Polygon(sides);//this is no longer the Rectangle when called

    function Polygon(sides){
                    if(this instanceof Polygon){
                        this.sides=sides;//sides
                        console.log(this)
                        this.getArea=function(){
                            return 0;
                        }
                    }else{
                        console.log('Polygon'+this)
                        return new Polygon(sides);
                    }
                }
                
                function  Rectangle(wifth,height){
                    Polygon.call(this,2);
                    console.log(this)
                    this.width=this.width;
                    this.height=height;
                    this.getArea=function(){
                        return this.width * this.height;
                    };
                }
                
                var rect=new Rectangle(5,10);
                alert(rect.sides); 

    reply
    0
  • Cancelreply