Как происходит это «если», но на самом деле это не должно? - PullRequest
0 голосов
/ 18 июня 2011

Добрый день, сначала я хотел бы сказать, что я не горжусь размещением всего исходного кода.Я не смог выделить проблему в меньшем куске.

Вот снимок файла:

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
    }
},

, и весь файл находится там: http://jsfiddle.net/JSWCu/2/

Проблема: у меня есть метод, который проверяет аргументы против JS.Hash, содержащего объект.Надеемся, что if вернет истину, но, оказавшись внутри, я не смогу (ни предупредить, ни вернуть) объект внутри этого JS.Hash (возвращается неопределенное значение).

Спасибо!Ваша помощь очень ценится.Буду также признателен за советы, чтобы избежать таких ошибок.

Редактировать: вот целые коды.Извините, это действительно большой.Это только начинает усложняться, и я не мог (пока) изолировать проблемы в меньший кусок кода:

<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 = Informations;

                        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>

Ответы [ 3 ]

1 голос
/ 18 июня 2011

Отвечая на ваш вопрос в комментариях

как может пройти if, когда при возврате значения оно не определено

Вы используете сравнение this.hAreas.get( areaId )[ roomId ] !== undefined.Что это будет делать, так это проверить, что значение слева не строго равно этому конкретному экземпляру undefined.Если вы имеете дело с несколькими окнами / фреймами, возможно иметь разные экземпляры undefined (потому что каждое окно имеет свой undefined).Если это звучит действительно странно, это потому, что это так.

Чтобы защититься от этого, вы обычно видите это сравнение, записанное как:

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

... которое проверяет, что тип операнда является «неопределенным» (обратите внимание на кавычки), что является надежным перекрестным окном.

1 голос
/ 18 июня 2011

Я играл с вашим примером на jsfiddle и столкнулся с довольно странным поведением. В вашем Character class 'initialization методе вы вызываете соответствующий метод World.getRoomById() и присваиваете его переменной petRoom.

Как ваш код стоит, когда вы alert(petRoom) вы получаете undefined. Тем не менее, если вы alert(petRoom.roomId) получите 000003, как предполагалось, так что я предполагаю, что на самом деле не возвращается true undefined. Если вы зарегистрируете petRoom в консоли chrome, он классифицирует его как конструктор, а не как объект. Я не совсем уверен, что там происходит, но я подумал, что это даст дополнительное направление. Я продолжу играть .....

ОБНОВЛЕНИЕ: Проблема в том, что вы переопределяете метод Room class 'toString() и ничего не возвращаете. По умолчанию оповещение о чем-то приводит его к строке, используя метод toString() объекта, и поскольку вы переопределили это и не возвращаете значение, вы получите неопределенное значение.

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

        }
});
0 голосов
/ 18 июня 2011

Попробуйте вместо этого:

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