I noticed recently that when "use strict";
mode is on in browsers many properties on native objects become unsettable.
For example
function() { "use strict"; var div = document.createElement("div"); div.offsetLeft = 0; }();
Ignore the fact that setting offsetLeft
is stupid. That's not the point.
If you run this in Chrome or Firefox you'll get an error
Uncaught TypeError: Cannot set property offsetLeft of #<HTMLElement> which has only a getter(…)
Remove the "use strict";
and the error goes away.
So here's the problem. Let's change offsetLeft
to something I might use in my own code
function createElementAndAssociateData(data) { "use strict"; var div = document.createElement("div"); div.userdata = data; };
This works great, except 2 years from a new HTML5 spec comes out and decides that all HTMLElements have userdata
attribute that's read only. Suddenly my code breaks everywhere I used "use strict";
.
Is this a time bomb waiting to happen as more and more properties are added to native HTML5 objects?
Is there a safe way to use "use strict";
and add custom properties to native HTML5 objects or should adding any kind of property to a native browser object never be done?
Note: I don't believe obfusticating the property names is an acceptable solution. Sure I could change userdata
to mycompanyname_myappname_userdata
but that's kind of beside the point. Is there some other solution or is adding custom properties to native HTML5 objects in strict mode an anti-pattern?
Yes: ES6 symbols
The problem with properties is that their name is a string. Then, two different codes may choose to use the same name for different purposes, and the result may be disastrous.
To solve this problem, ECMAScript 6 introduces a new type: Symbol.
You can use it like this:
var s1 = Symbol("My property"); object[s1] = "Some data 1"; object[s1]; // "Some data 1"
Then, even if some other code decides to use a symbol with the same description, there won't be any collision:
var s2 = Symbol("My property"); // Same description :S object[s2] = "Some data 2"; object[s2]; // "Some data 2" object[s1]; // "Some data 1" -- No problem :)
The intended way of adding custom properties is with HTMLElement.dataset
.
var div = document.createElement("div"); div.dataset.yourCustomProperty = 'some data'; div; // <div data-your-custom-property="some data"> div.dataset.yourCustomProperty; // "some data"
This reflects the custom data-*
attributes.
Note that .dataset.camelCase
reflects data-camel-case
and the other way round.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With