tags:

views:

42

answers:

1

When creating lots of DOM elements, document.createElement and friends can add lots of bytes and ugliness. I know I could make my own subroutine, or use innerHTML or whatever, but why can't I just do this:

var $c = document.createElement;
var newP = $c('p');

Firebug complains with this message:

"Illegal operation on WrappedNative prototype object" nsresult: "0x8057000c (NS_ERROR_XPC_BAD_OP_ON_WN_PROTO)"

Clearly I've done something that is Not Allowed. Why isn't it? It's allowed for other things, e.g. Array.splice or Math.min.

+6  A: 

The way you are invoking it, causes the this value inside the createElement method to refer to the global object.

I would recommend you to simply use a function:

var $c = function (tagName) { return document.createElement(tagName); };
var newP = $c('p');

The behavior I talk can be described with an example:

var foo = 'global foo';

var obj = {
  foo: "I'm obj.foo",
  method: function () {
    return this.foo;
  }
};


var fn = obj.method;

obj.method(); // "I'm obj.foo"
fn();         // "global foo"
CMS
I think I get it. Doing `fn = obj.method` assigns the `method` method to the global `fn` variable, "freeing" it from the scope of the object. So in my example, the scope of `document` is lost and that is why the console complains. Is this correct? And if so, why don't Math.min and Array.splice complain when this is done to them?
Rafael
@Rafael, right, with the `Math` methods it doesn't happen, because they are *"static"*, they don't use the `this` value internally. About "`Array.splice`", I suppose you are talking about the Mozilla's ["Array Generics"](https://developer.mozilla.org/en/New_in_JavaScript_1.6#Array_and_String_generics), those methods are also *"static"*, but keep in mind that they are *not* part of the ECMAScript Standard, they are available only in Mozilla implementations... `Array.splice != Array.prototype.splice`
CMS
That clears it all up. Thank you very much for your clear explanations.
Rafael
@Rafael, You're welcome! Also a more *correct terminology* of your phrase: '"freeing" it from the scope of the object', would be "loosing the reference's base object". This is not related at all to the *scope*, it's has to do with how the [Reference Spec. Type](http://ecma262-5.com/ELS5_HTML.htm#Section_8.7) and [function calls](http://ecma262-5.com/ELS5_HTML.htm#Section_11.2.3) internally work.
CMS