I'm writing a JavaScript Library that offers the function tablify(anything);
, which is able to represent any Array or Object as an HTML Table.
Now I'm trying to extend the Array and Object prototypes in order to use it like this:
var arr = ["a", "b", "c"];
var obj = {"A": "a", "B": "b", "C": "c"};
arr.tablify();
obj.tablify();
This is my approach:
Array.prototype.tablify = function() {
return tablify(this);
}
Object.defineProperty(Object.prototype, 'tablify', {
value: function () {
return tablify(this);
},
writable: true,
configurable: true,
enumerable: false
});
The issue is, that everything in JavaScript is an Object and therefore not only literals like {a: 1, b: 2}
can be converted, but also everything else.
This wouldn't be such a big deal since my tablify()
can also deal with primitive types, but when I extend Object.prototype, typeof anything
always returns "object"
and I can't distinguish between types anymore:
function tablify(object) {
if (object instanceof Array) {
return ArrayToTable(object);
}
//This is always true if I extend Object.prototype:
if (typeof object === "object") { //only for "normal" objects like "{a: 1, b: 2, c: [],...}"
return ObjectToTable(object);
}
return PrimitiveToTable(object); //strings, numbers, functions, ...
}
- Why is
typeof
always returning"object"
? - Is it a good thing for a JS-API to provide this sort of functionality (extending Arrays/Objects with ".tablify();")?
- How is it possible to distinguish between "normal" objects, numbers, functions,... ?
- Is it possible to only extend "normal" objects?
(forbid
(42).tablify();
,"string".tablify();
...) - Whats the name for those "normal" objects? How should I call them?
Because in sloppy mode, the
this
context always is supposed to be an object. When you call a function or pass undefined or null, you get the global object, when you call a method the context will get casted to an object.Use strict mode for your
tablify
method and it will work!Yes. No.. Many people will frown to use your script when you want to share it. See Why is extending native objects a bad practice? for a detailed discussion.
At least you've properly used non-enumerable properties - but I would recommend to use them on
Array.prototype
as well, too many people abusefor in
enumerations.typeof
seems fine.Not really. All primitive wrappers inherit from
Object.prototype
.Just "objects". Or "plain objects" if you want (distinguishes them from arrays, built-ins, host objects).
The problem is that once you get into your newly-added method on the prototype, the original primitive value has already been converted. For example:
In that call, before the function is called, the string primitive is converted into a String instance. In other words, it behaves as if you had written:
I suppose you could use the
Object.prototype.toString
function to tell the difference:You won't be able to tell if the boxed primitive was implicitly created or not, but that probably doesn't really matter for what your code does anyway.