Acceder a la variable global de JavaScript por segunda vez da como resultado indefinido

Tengo el siguiente código javascript:

<script type="text/javascript">
   var x = 10;
   window.onload = function() {
      document.write(this.x); // <-- yields correct output: 10.
      document.write(this.x); // <-- outputs "undefined"
      document.write(this.x); // <-- outputs "undefined"
   }
</script>

I am unable to understand why [this.x] results in undefined from the second time onwards. If I am correct, the function context (value of "this"), would refer to the global window object.

preguntado el 10 de marzo de 12 a las 15:03

outputs "undefined" -- Actually, it doesn't. jsfiddle.net/Tomalak/dt4dg You are doing something different from what you show here. -

I would just output it to a DOM element using innerHTML, or log it to the console -

@Tomalak: I am absolute positive, what i have written is what i am doing :). My intention to write this code was to understand "this". Point me in right direction, if in case i am wrong. Thanks. -

@thescientist: Is there any problem if i use document.write(this.x)? -

@jfriend00: It's nothing special i want to achieve here. It's just the five lines of code I want to execute. That's it. The reason to post this query is, if I write document.write(x), it works fine. But if i write document.write(this.x), it fails to execute. Just want to understand, why is this happening? -

4 Respuestas

Cuando se utiliza document.write() AFTER the document has loaded, it opens a new document (clearing the previous one). It appears that in some browsers (IE, for example), the global variables are immediately wiped out, even from the script that is still running that did the document.write(). The best answer here is to not use document.write() after the page has loaded. Instead, use DOM manipulation to change the existing document however you want it changed rather than creating a new document. You can see that things work fine (based on your more recent code example) if you use DOM manipulation (manipulating innerHTML) rather than using document.write() in este jsFiddle.

Since clearing the current document is almost never what you want to do, if you can explain what you're really trying to accomplish we can help better with a solution.

Si deseas modify the existing document after it has loaded, you need to use DOM manipulation functions such as .innerHTML (to change the HTML of a node) or DOM manipulation functions to add new nodes to the existing document, NOT document.write().

You should generally not use this to refer to global variables. Global variables are available with no prefix (unless overriden locally) or available with the window prefijo.

So, either of these will work:

<script type="text/javascript">
   var x = 10;
   window.onload = function() {
      console.log(x);
      console.log(x);
      console.log(x);
   }
</script>

<script type="text/javascript">
   var x = 10;
   window.onload = function() {
      console.log(window.x);
      console.log(window.x);
      console.log(window.x);
   }
</script>

As to your question about using this. El valor de this is set one of several ways:

  1. When you call a method on an object such as pleasures.makeIceCream(), El valor de this se establecerá en el pleasures objeto en el makeIceCream() método.
  2. Cuando se utiliza el call method on function objects like makeIceCream.call(pleasures), entonces el valor de this se establecerá en el pleasures object in this invocation of the makeIceCream() método.
  3. Cuando se utiliza el apply method on function objects like makeIceCream.apply(pleasures), entonces el valor de this se establecerá en el pleasures object in this invocation of the makeIceCream() método.

Puedes leer más sobre la .call() y .apply() in these MDN references:

aplicar: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/apply

llamada: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/call

At all other times, the value of this should generally not be used as it has not been explicitly set. It is likely set to the global object (in a browser, this is the window object) , but it is not considered best practice to use it to access global variables, nor is there any reason to.

respondido 10 mar '12, 18:03

I agree with you on the concept, and I would used the best practices in my project. But as you told: "At all other times, the "this" would refer to global object", I just want to understand, whats the problem accessing document.write(this.x) the second time onwards. For this sample, I am focusing on the concept and not the best practices. I hope you understand my concern. If i write "alert" instead of "document.write", it works fine. - Anup Vasudeva

@AnupVasudeva - Probably the first document.write() wipes out the existing document (in some browsers) and all its global variables as a brand new document is created. Thus anything that used to exist as a global object would no longer exist. As I've said four times, now don't use document.write() after the document has loaded. What part of this am I not communicating effectively? - amigo00

Your jsFiddle works fine in Chrome, doesn't work in IE. Obviously IE behaves differently when you use document.write() after the document has been loaded. It loses access to global variables in running scripts, where Chrome doesn't. What you are doing is not a supported behavior. There are other ways to do that (direct DOM manipulation) that don't have this issue. That would be the way to solve your issue. To prove this, try este jsFiddle in IE. It works fine when not using document.write(). - amigo00

I agreed with you before, that document.write isn't a good practice at all. I also conveyed my intention, as it's just for the sample purpose, and not for best practice (though i appreciate your effort). All I want to understand why Javascript behaves in this way if I write such code. This will help other people understand that there maybe some connection between document.write and global variables. Rest, I am also researching more on this. - Anup Vasudeva

It is clear that IE removes access to the global variables from a running script when you use document.write() after the page has loaded. My point was that it's a bad practice and there are better ways to accomplish modifying the document so I'm unsure why you're spending time trying understand the browser-dependent behavior of a bad practice that has an alternative that is a good practice. I think I've said all I can say here. - amigo00

since it is a global variable, you need not use object. try this

var x = 10;
window.onload = function() {
    document.write(x);
    document.write(x);
    document.write(x);
}

violín : http://jsfiddle.net/dt4dg/1/

respondido 10 mar '12, 16:03

Thanks rajkumar. I know this works well. But I am trying to figure out the reason why document.write(this.x) doesn't works. When the window.onload function gets called, the function context (this) will always be a window object. - Anup Vasudeva

I would just use this:

document.write(x);

Since it is defined outside of the function it can be called within the function.

respondido 10 mar '12, 15:03

Is there any issue prefixing "this" with x? - Anup Vasudeva

It ain't working because you is calling document.write after page has loaded. Calling write will implicitly mean you are creating a new page immediately. The new page does not understand the value of x.

respondido 10 mar '12, 16:03

but it seems the Javascript is understanding "document.write(x)" and not "document.write(this.x)". Is there any difference between the two? - Anup Vasudeva

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.