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"
精彩评论