PDA

View Full Version : object existence and access



brentnicholas
08-05-2008, 04:25 PM
Hi,

So I need to verify something from those who do a lot of object based js.

In plain english: I create a new object in the init() function that is fired off when the window completes loading. I then want to pass that object to another function by mouse click on an href.

I keep getting object does not support property or method. If I do an alert on 'map', I get an object.

I just want to verify that I can pass the 'map' object into a function in this manner.

Thanks!
BN

example:

<script>
window.onload = function() {
init();
};

function init(){
var map = new OpenLayers.Map( 'map',{maxResolution: 0.703125} );
}

function callMe(lonlat,map){
alert(map.getLayers());
}
</script>

<a href="javascript:callMe('40.1135,-111.8535',map);">click it</a>

jscheuer1
08-05-2008, 05:19 PM
You should be able to do that. From the code you show I don't think you should be getting the error you are reporting, though. The var map is not in the global scope. However, perhaps it is and you just haven't shown how that happens. If so, perhaps the:


getLayers()

method is not supported for the map object.

But it could be something else. Try just:


function callMe(lonlat,map){
alert(typeof map);
}

It should say object. Then the problem is the getLayers() method. But if it says undefined, it means either that the map variable isn't in the global scope, or that it hasn't been passed/called properly.

This is bad form:


<a href="javascript:callMe('40.1135,-111.8535',map);">click it</a>

It should be:


<a href="#" onclick="callMe('40.1135,-111.8535',map);return false;">click it</a>

I could probably tell exactly what the problem is if I had a link to the page.

brentnicholas
08-05-2008, 05:50 PM
John,

Thanks for taking the time to reply.

I cleaned up the bad form anchor and did the type of, it returned an object. Though still breaks. The getLayers still does not work. ( it's actually called getNumLayers() ) But that doesn't matter for discussion.

Here is a link to the function I'm calling. it should be fine...
http://dev.openlayers.org/releases/OpenLayers-2.6/doc/apidocs/files/OpenLayers/Map-js.html#OpenLayers.Map.getNumLayers

I'm going to see if I can't make this link live so you can see what I'm doing.

BN

jscheuer1
08-05-2008, 06:26 PM
I just realized that if you are using IE or any browser and your page is in quirksmode, and have an element on the page with an id of 'map', it all makes perfect sense. This means that your variable map isn't in the global scope and that IE is picking up on the element with an id of 'map' (which would still be an object, just not the right kind for the method you are using) as part of the implied document.all collection.

If that's it, all you need to do is to put your var map in the global scope. From your example code (changes highlighted):


var map;
function init(){
map = new OpenLayers.Map( 'map',{maxResolution: 0.703125} );
}

blm126
08-05-2008, 11:52 PM
var map;
function init(){
map = new OpenLayers.Map( 'map',{maxResolution: 0.703125} );
}
This was just bothering me. :) Maybe I'm just weird, but I would write it like this.


function init(){
window.map = new OpenLayers.Map( 'map',{maxResolution: 0.703125} );
}
I like this way, because one can tell with just a glance where in the scope chain it is being stored. When I write JavaScript I use the window.* form for all global variables to help me keep track of things.

jscheuer1
08-06-2008, 12:39 AM
I like this way, because one can tell with just a glance where in the scope chain it is being stored. When I write JavaScript I use the window.* form for all global variables to help me keep track of things.

That's a pretty bad idea because the window object is a native object in javascript and, more importantly, in the browser. It already has native properties which vary by browser. As your code is ported to these various user agents, you may be overwriting a native property of the window object in a given browser. Or worse, you may attempt to overwrite a read only native property. In the first case it could cause unexpected results. In the second case, your script simply will not work.

Now, declaring a global variable (as I suggested with var map;) isn't all that bad. But you do want to avoid filling up the global scope with variables that may conflict with other scripts. Generally a well written script will have just one global variable, a unique object. All other values that need to be available in the global scope can be assigned as properties of that object.

Even better (but not always feasible) is to write out all of your code as an anonymous function, that way there will be nothing in the global scope. And if all of your variables are formally declared, no chance of your code being interfered with by other scripts.

I didn't go into all that in this case though, as sometimes it is best to move one step at a time with folks and not introduce too many ideas at once.

blm126
08-06-2008, 03:10 AM
That's a pretty bad idea because the window object is a native object in javascript and, more importantly, in the browser. It already has native properties which vary by browser. As your code is ported to these various user agents, you may be overwriting a native property of the window object in a given browser. Or worse, you may attempt to overwrite a read only native property. In the first case it could cause unexpected results. In the second case, your script simply will not work.

What?


<script type="text/javascript">
var test = true;
alert(window.test);//Will output true
</script>

The use of the "var" keyword when not in a block scope(aka global scope) causes that variable to be a property on the global object. In client-side JavaScript, the global object is Window. The global Window object contains a self-referential property called window that can be used to access it's properties and methods(which includes things like Math,Array,etc.)

jscheuer1
08-06-2008, 03:24 AM
What I said about native properties is still valid though. Just because what you do 'works' (sometimes) doesn't make it a good idea. Having a variable in the global scope that hasn't been formally declared often 'works', but is never a good idea. To understand what I'm talking about a little better, try this in a couple of different browsers:

<script type="text/javascript">
alert (typeof window.opener);
alert (typeof window.test);
</script>

blm126
08-06-2008, 03:47 AM
I think your missing the point I'm trying to make.


var test = "global var";

is exactly equivalent to


window.test = "global var";

For example, what do you think will happen if I do this


<script type="text/javascript">
function onload(){
alert("loaded");
}
</script>

There is absolutely no difference than the form most people use.

jscheuer1
08-06-2008, 04:06 AM
var test = "global var";

is exactly equivalent to


window.test = "global var";


No, there is a difference, which I already pointed out concerning native properties of the window object and how these will play out in different browsers. Your onload example proves that. It will not be an onload event in some browsers, as I believe you intend it to be. Or if you didn't intend it to be one, it will be in some browsers. Either way it is unreliable.