2

I have code like

<div id="loadCommentBestComment" style="cursor:pointer" onclick="createComment('af0532_$dvkpo6420')">load the most useful comment.</div>

The problem was that I was clicking on it and nothing was executing, the function createComment() wasn't even being called.
hours tried to figure out what was going on but nothing. Then tried to change the name of createComment to another name like createCommentAlias() and everything worked fine.
this is not the first time this happens, I have gotten weird behaviours of this kind previously as well. and again due to variable names which seemingly were overriden by other native variables.
Another example, the name nextSibling is a method of a Dom element, and thus can normally be used as var nextSibling, but in inline js it gets, again, overriden by something else. And again this happens only if the js is inline.
So I'd like to know what are these variable, where do they come from, and possibly have a list of them so that I don't use those names again.

Core_dumped
  • 1,571
  • 4
  • 16
  • 34
  • Related: [JS function named `animate` doesn't work in Chrome, but works in IE](http://stackoverflow.com/q/28173800/1529630). – Oriol Apr 04 '15 at 20:44

1 Answers1

2

The problem is that, since you use an event handler content attribute, your global function...

window.createComment

...is shadowed by...

Document.prototype.createComment

This behavior is explained in step 10 of getting the current value of the event handler:

Lexical Environment Scope

  1. If H is an element's event handler, then let Scope be the result of NewObjectEnvironment(document, the global environment).

    Otherwise, H is a Window object's event handler: let Scope be the global environment.

  2. If form owner is not null, let Scope be the result of NewObjectEnvironment(form owner, Scope).

  3. If element is not null, let Scope be the result of NewObjectEnvironment(element, Scope).

Note: NewObjectEnvironment() is defined in ECMAScript edition 5 section 10.2.2.3 NewObjectEnvironment (O, E)

That means that the global scope is shadowed by

  1. The document
  2. The form owner, if any
  3. The element

Therefore, you can

  • Rename your function

    function createComment__() {
      var div = document.getElementById('loadComment');
      div.style.left = "200px";
      div.style.color = "red";
    }
    #loadComment {
      position: absolute;
    }
    <p id="loadComment" onclick="createComment__()">lolol</p>
  • Use window.createComment (assuming window is not shadowed):

    <p id="loadComment" onclick="window.createComment()">lolol</p>
    

    function createComment() {
      var div = document.getElementById('loadComment');
      div.style.left = "200px";
      div.style.color = "red";
    }
    #loadComment {
      position: absolute;
    }
    <p id="loadComment" onclick="window.createComment()">lolol</p>
  • Avoid event handlers content attributes:

    document.getElementById('loadComment').onclick = createComment;
    

    function createComment() {
      var div = document.getElementById('loadComment');
      div.style.left = "200px";
      div.style.color = "red";
    }
    document.getElementById('loadComment').onclick = createComment;
    #loadComment {
      position: absolute;
    }
    <p id="loadComment">lolol</p>

The only safe approach is the third one, because you can't be sure if some browsers implement a non-standard feature which shadows your variables. Or a future spec could introduce that feature (see example).

Community
  • 1
  • 1
Oriol
  • 274,082
  • 63
  • 437
  • 513