Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is this "invalid calling object" error?

Tags:

javascript

I write the following JS and run in IE 10:

function test() {
    var nodes = document.getElementsByTagName("h1");
    document.writeln(nodes.length);
    for (var j = 0; j < nodes.length; j++) {   <=== THIS LINE!
        document.writeln(j.toString());
        }
    document.writeln("abc");
}

But I kept get "invalid calling object" error for the marked line.

Why?

And here is my page source:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
    <head>
        <title>This is JS fun!</title>
        <script type="text/javascript" language="javascript" src="test.js">
        </script>
    </head>
    <body>
        <h1>1111</h1>   
        <h1>2222</h1>   
        <h1>3333</h1>   
        <h1>4444</h1>   
            <input type="button" onclick="test()" value="click me!" />
    </body>
</html>

Below is my screenshot:

enter image description here

like image 878
smwikipedia Avatar asked Oct 20 '12 15:10

smwikipedia


2 Answers

The error comes because you are running the code after the page is completed.

The first document.writeln call creates a new document with only the string in it. That means that the collection in nodes is no longer valid. It is a collection of elements in a document that doesn't exist any more, so you can't use any of the properties (like length) of the collection any more.

If you run the code while the page is being created, it works fine: http://jsfiddle.net/Guffa/4w949/

like image 150
Guffa Avatar answered Nov 06 '22 18:11

Guffa


OK, I may have figured it out.

I tried this:

function test() {
    var nodes = document.getElementsByTagName("h1");
    document.writeln(nodes.length); // 1st writeln
    nodes2 = document.getElementsByTagName("h1");
    alert(nodes2.length);  //  <========= MARK1
    for (var j = 0; j < nodes2.length; j++) {
        alert(j);
            }
    document.writeln("abc");
}

No error for above code. but the MARK1 line gives 0. Because after the 1st writeln, the complete page content is re-constructed, there's no < h1 > tag in the newly constructed page any more.

And then I changed the above code to this:

 function test() {
    var nodes = document.getElementsByTagName("h1");
    document.writeln(nodes.length + "<h1>new h1</h1>");   // ADD a new < h1 > tag
    nodes2 = document.getElementsByTagName("h1");
    alert("node2 length = " + nodes2.length);   //MARKED
    for (var j = 0; j < nodes2.length; j++) {
        alert(j);
            }
    document.writeln("abc");
}

Now the MARKED line gave me expected length, 1. Because I put a new < h1 > tag into the newly constructed document.

As to the Invalid Calling Object error. I think because the document is re-constructed with writeln, all the DOM objects previously obtained with the old invalidated document object will be invalided, too.

The key is the implicit creation of a new document by document.writeln method.

Please correct me if I am wrong.

Thanks Guffa for the insight.

like image 40
smwikipedia Avatar answered Nov 06 '22 18:11

smwikipedia