开发者

How comes this "if" passes but for real it shouldn't?

Good day, first I would like to tell that I am not proud to post a whole source code. I couldn't isolate the problem in a smaller chunk.

Here is a snapshot of the file:

getRoomById : function( areaId, roomId ) {
    if ( this.hAreas.get( areaId ) !== null && this.hAreas.get( areaId )[ roomId ] !== undefined )
    {
        //I can get here...
        //alert( uneval( this.hAreas.get( areaId ) ) );
        // returns: ({'000001':{areaId:"000001", roomId:"000001", Informations:{Name:"Room 1"}}, '000002':{areaId:"000001", roomId:"000002", Informations:{Name:"Room 2"}}, '000003':{areaId:"000001", roomId:"000003", Informations:{Name:"Room 3"}}})

        //alert( roomId );
        // returns: 000003

        return this.hAreas.get( areaId )[ roomId ];
        // returns: undefined
    }
},

and the whole file is there: http://jsfiddle.net/JSWCu/2/

The problem: I have a method which tests the arguments against a JS.Hash containing an object. That if hopefully returns true but once inside, I can't get (either alert or return) the object inside that JS.Hash (an undefined is returned).

Thank you! your help is greatly appreciated. I would also appreciate tips to avoid such errors.

Edit: here is the whole codes. Sorry It's really big. It's just starting to get complex and I couldn't (for now) isolate the problems to a smaller piece of codes:

<html>
    <head>
        <style type="text/css">

        </style>
        <script type="text/javascript">
            JSCLASS_PATH = 'http://www.poc.ca/cybrix/src';
            function appendConsole( input ) {
                document.getElementById( "console" ).innerHTML += input + "<br />";
            }
        </script>
        <script type="text/javascript" src="http://www.poc.ca/cybrix/src/loader-browser.js"></script>
        <script type="text/javascript">
            JS.require('JS.Hash', 'JS.Observable', function() {
                var AreaLists = {
                    "000001" : { "Name" : "Test Area", "Loaded" : false },
                };

                var World = new JS.Class({
                    hAreas : new JS.Hash([]),

                    getAreas : function( areaId ) {
                        if ( ! this.hAreas.get( areaId ) && AreaLists[ areaId ] !== undefined )
                        {
                            //TODO: Load from external sources

                            this.hAreas.put( areaId, {
                                "000001" : new Room( areaId, "000001", { "Name" : "Room 1" } ),
                                "000002" : new Room( areaId, "000002", { "Name" : "Room 2" } ),
                                "000003" : new Room( areaId, "000003", { "Name" : "Room 3" } ),
                            });

                            AreaLists[ areaId ].Loaded = true;

                            appendConsole( "Areas #" + areaId + " : " + AreaLists[ areaId ].Name + " Created" );
                        }

                        return this.hAreas.get( areaId );
                    },
                    getRoomById : function( areaId, roomId ) {
                        if ( this.hAreas.get( areaId ) !== null && this.hAreas.get( areaId )[ roomId ] !== undefined )
                        {
                            //I can get here...
                            //alert( uneval( this.hAreas.get( areaId ) ) );
                            // returns: ({'000001':{areaId:"000001", roomId:"000001", Informations:{Name:"Room 1"}}, '000002':{areaId:"000001", roomId:"000002", Informations:{Name:"Room 2"}}, '000003':{areaId:"000001", roomId:"000003", Informations:{Name:"Room 3"}}})

                            //alert( roomId );
                            // returns: 000003

                            return this.hAreas.get( areaId )[ roomId ];
                            // returns: undefined
                        }
                    },
                    reloadAreas : function( areaId ) {
                        //Triggered by Tick only if there is no players
                    },

                    addCharacter : function( areaId, roomId, character ) {
                        if ( this.hAreas.get( areaId ) && this.hAreas.get( areaId )[ roomId ] )
                        {
                            this.hAreas.get( areaId )[ roomId ].addCharacter( character );
                        }
                    },
                    removeCharacter : function( areaId, roomId, character ) {
                        return this.hAreas.get( areaId )[ roomId ].removeCharacter( character );
                    }
                });

                var Room = new JS.Class({
                    hDoors : new JS.Hash([]),
                    hExits : new JS.Hash([]),
                    hBodies : new JS.Hash([]),
                    hObjects : new JS.Hash([]),

                    initialize : function( areaId, roomId, Informations ) {
                        this.areaId = areaId;
                        this.roomId = roomId;
                        this.Informations = Informations;

                        //TODO: Load from external sources
                        if ( areaId == "000001" && roomId == "000003" )
                        {
                            this.hObjects.put("000001", new Objects("000001", { "Name" : "A table", "Type" : 0 }) );
                            this.hObjects.put("000002", new Objects("000002", { "Name" : "A water fountain", "Type" : 1 }) );
                        }

                        appendConsole( "Room: #" + this.areaId + "-" + this.roomId + " : " + this.Informations.Name + " Created" );
                    },

                    addCharacter : function( character ) {
                        this.hBodies.put( character.characterId , character );

                        character.onArriveRoom( this );

                        if ( ! character.Informations.Stealth )
                        {
                            //TODO: Broadcast Informations to others

                            appendConsole( character.Informations.Name + " has arrived to " + this.Informations.Name );
                        }
                    },
                    removeCharacter : function( character ) {
                        var characterId = ( typeof character == "object" ) ? character.characterId : character,
                            currentCharacter = this.hBodies.remove( characterId );

                        character.onLeaveRoom( this );

                        if ( currentCharacter !== null )
                        {
                            //TODO: Broadcast Informations to others

                            appendConsole( character.Informations.Name + " has left " + this.Informations.Name );

                            return currentCharacter;
                        }

                        return undefined;
                    },

                    onArrive : function() {

                    },

                    onLeave : function() {

                    },

                    getObjects : function( objectId, hash ) {
                        if ( this.hObjects.get( objectId ) )
                        {
                            var currentObjects = this.hObjects.get( objectId );

                            if ( hash )
                            {
                                return new JS.Hash([
                                    currentObjects.objectId, currentObjects 
                                ]);
                            }

                            return currentObjects;
                        }

                        return this.hObjects;
                    },

                    toString : function( characterId ) {

                    }
                });

                var Objects = new JS.Class({
                    objectsTypes : {
                        0 : "lies",
                        1 : "stands"
                    },

                    initialize : function( objectId, Informations ) {
                        this.objectId = objectId;
                        this.Informations = Information开发者_C百科s;

                        appendConsole( "Object: #" + this.objectId + " : " + this.Informations.Name + " Created" );
                    },

                    toString : function() {
                        return this.Informations.Name + " " + this.objectsTypes[ this.Informations.Type ] + " here.";
                    }
                });

                var Character = new JS.Class({
                    Pet : undefined,

                    initialize : function( characterId, Informations ) {
                        this.characterId = characterId;
                        this.Informations = Informations;
                        this.areaId = this.Informations.Zone.split("-")[ 0 ];
                        this.roomId = this.Informations.Zone.split("-")[ 1 ];

                        if ( this.Informations.Pet !== undefined )
                        {
                            //TODO: Load from external sources

                            if ( this.Informations.Pet === "000001" )
                            {
                                this.Pet = new Pet( "000001", { "Name" : "Molten Panther", "Zone" : this.areaId + "-" + this.roomId, "Stealth" : false } );

                                World.addCharacter( this.Pet.getArea() , this.Pet.getRoom() , this.Pet );

                                var petRoom = World.getRoomById( this.Pet.getArea() , this.Pet.getRoom() );

                                alert( petRoom ); // = undefined ????
                            }
                        }

                        appendConsole( "Character: #" + this.characterId + " : " + this.Informations.Name + " Created" );
                    },

                    onArriveRoom : function ( currentRoom ) {

                    },
                    onLeaveRoom : function( currentRoom ) {

                    },

                    onArrive : function() {

                    },
                    onLeave : function() {

                    },

                    getRoom : function() {
                        return this.roomId + "";
                    },
                    getArea : function() {
                        return this.areaId + "";
                    },
                    getInformations : function() {
                        return this.Informations;
                    },
                    hasPet : function() {
                        return ( typeof this.Pet == "object" );
                    },
                    getPet : function() {
                        return this.Pet;
                    },

                    equals : function( character ) {
                        return ( character instanceof this.klass ) && character.Informations.Name === this.Informations.Name;
                    }
                });

                var Pet = new JS.Class( Character, {

                    initialize : function( characterId, Informations ) {
                        this.callSuper();

                        appendConsole( "Pet: " + this.Informations.Name + " Created" );
                    }
                });

                //Tests
                var World = new World();
                var AreaOne = World.getAreas( "000001" );

                var Cybrix = new Character( "000001", { "Name" : "Cybrix", "Zone" : "000001-000003", "Stealth" : false, "Pet" : "000001" } );

                if ( World.getAreas( Cybrix.getArea() ) )
                {
                    World.addCharacter( Cybrix.getArea() , Cybrix.getRoom() , Cybrix );

                    //Cybrix = World.removeCharacter( Cybrix.getArea() , Cybrix.getRoom() , Cybrix );
                }
            });
        </script>
    </head>
    <body style="margin: 0; padding: 0;">
        <div id="console" style="display: block; background-color: #000; height: 100%; color: #FFF; font-family: Lucida Console;"></div>
    </body>
</html>


I've been playing around with your example on jsfiddle and I'm running into some rather odd behavior. In your Character class' initialization method you're calling the World.getRoomById() method in question and assigning it to a variable called petRoom.

As your code stands, when you alert(petRoom) you do get undefined. However, if you alert(petRoom.roomId) you get 000003 as intended so my guess is it's not really returning a true undefined. If you log petRoom to chrome's console it classifies it as a constructor and not an object. I'm not really sure what's going on there, but I thought it'd give some extra direction. I'll keep playing.....

UPDATE: The issue is that you're overriding the Room class' toString() method and not returning anything. By default, alerting something cast it to a string using the object's toString() method and because you've overridden that and aren't returning a value you get undefined.

var Room = new JS.class({
        ...
        snip
        ....
        toString: function(characterId) {

        }
});


Answering your question in the comments

how could the if passes when once you return the value it is undefined

You're using the comparison this.hAreas.get( areaId )[ roomId ] !== undefined. What that will do is test that the value on the left isn't strictly equal to that specific undefined instance. If you're dealing with multiple windows/frames, it's possible to have different undefined instances (because each window has its own undefined). If that sounds really weird, it's because it is.

To guard against that, you usually see that comparison written as:

if (typeof this.hAreas.get( areaId )[ roomId ] !== "undefined")

...which tests that the type of the operand is "undefined" (note the quotes), which is reliable cross-window.


Try this instead:

typeof this.hAreas.get( areaId )[ roomId ] !== "undefined"
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜