Peter Street Peter Street - 1 month ago 8
HTML Question

Is Object.getPrototypeOf(val).toString() safe to ensure DOM types?

I am writing a piece of library code for internal development at my company, so this is purely a personal satisfaction question - if there are issues, our error logging will note it pretty quickly and we'll be able to do updates... I'd just like to avoid those if possible :D

The library needs to operate on

<th>
or
<td>
values passed in that are either sourced from
document.get...
,
document.createElement
or
onmousedown
events. I've had issues when the wrong sort of object (i.e. non-
th
/
td
) went into the function, so I've put a fail-out clause at the top of the function:

function doSomething (cell) {
var _objName = Object.getPrototypeOf(cell).toString();
if (_objName.indexOf("HTMLTableCellElement") === -1 &&
_objName.indexOf("HTMLTableHeaderCellElement") === -1) {
// log error
return false;
}

// normal work here
}


Is this safe? I'm targetting modern (IE 10+, Chrome) browsers within our company, and it seems to work at the moment:


  • IE returns
    "[object HTMLTableCellElementPrototype]"
    (For
    <TD>
    ) or
    "[object HTMLTableCellHeaderElementPrototype]"
    (for
    <TH>
    )

  • Chrome returns
    "[object HTMLTableCellElement]"
    for both



I'm concerned that I'm relying on a non-documented implementation detail and things are going to break when we move to other browsers or browsers are updated.

Is this safe, or should I be using another method to ensure correct input? Some of this input is going to be from things the user has clicked on, so there definitely will be invalid input going to the function...

Answer

should I be using another method to ensure correct input?

Yes. Using toString might work, but checking class names is never a really good idea.

Instead, simply use .tagName to check whether an element of the right kind was passed:

if (cell.tagName != "TD" && cell.tagName != "TH") { return false; }

Alternatively, you could use a DOM selector like in

if (!cell.matches("td, th")) { return false; }

but cross-browser support for .matches() isn't that good.