window.addEventListener('keydown',function(e) {
const key= document.querySelector(`div[data-key='${e.keyCode}']`);
console.log(key.className);
console.log(key.classList);
key.classList=['ajay','dish'];
}
<div data-key="65" class="key ajay">
<kbd>A</kbd>
</div>
Above is a screenshot of chrome devtools with values modified.
I read on MDN that element.classList
is read only property but can be modified by add()
etc.
I assigned it to some other array and that is working too.
In other cases, whenever I tried to modify/assign read only property, it always gave typeError
.
The Element.classList is a read-only property that returns a live DOMTokenList collection of the class attributes of the element. This can then be used to manipulate the class list. Using classList is a convenient alternative to accessing an element's list of classes as a space-delimited string via element.className .
toggle() The toggle() button is used for toggling classes to the element. It means adding a new class or removing the existing classes.
toggle() will add the CSS class if it does not exist in the classList array and return true . If the CSS class exists, the method will remove the class and return false . The classList. toggle() method supports adding and removing CSS classes whether they exist or not in your array with shorter lines of code.
Very good question.
I did not originally know the exact answer to your question, but I'm not surprised as much by the behaviour. The spec defines the minimum that all compliant useragents (browsers) must implement. It also defines all the features that developers can expect and rely on when targeting compliant useragents (browsers). It's up to the browsers to add additional non-standard features.
This means that all browsers have to implement a get
property called classList
. Developers should only expect a get
property to be available in browsers. Browsers might think it's convenient for developers to have a set
function implemented too. It's fairly common for browsers to do this kind of thing. Sometimes this kind of features gets added to a newer version of the standard, sometimes it never makes it because the standard committee disagrees with the purity of the feature.
Sometimes non-standard features get deprecated and even removed, which although takes years - is a good reason for developers to not rely on non standard features when other standard features can achieve the same goal (for example, the property className
can be used to override the classList
).
Chrome implements this in a very clever way (might be originally WebKit). It applies an attribute PutForwards
to the definition of classList
.
This allows the property to be defined as readonly
, but when assigned a value, one of the properties of the object gets assigned instead, not the entire object. In this case, the child property name is value
.
So, the code document.body.classList = '123';
is the same as document.body.classList.value = '123';
You can confirm the object was not replaced by running the following in Chrome console
const body = document.body;
const oldClassList = body.classList;
const oldValue = body.classList.value;
body.classList = "new-class";
const newClassList = body.classList;
const newValue = body.classList.value;
console.log(
"classList changed:", oldClassList !== newClassList, // false
"value changed:", oldValue !== newValue // true
);
The definition of classList
in Chromium source code
[Affects=Nothing, SameObject, PerWorldBindings, PutForwards=value] readonly attribute DOMTokenList classList;
can be found at: https://github.com/chromium/chromium/blob/4141778eb03a31a20d9e109f74faf2f756b4a8c4/third_party/blink/renderer/core/dom/element.idl#L37
Note how this is different from the definition in the spec
[SameObject] readonly attribute DOMTokenList classList;`
which can be found at https://www.w3.org/TR/dom/#element
And the test in the source code that explains the relation between the attribute and the ability to override the readonly property in its comment
// Even though classList is readonly, PutForwards=value means that its value is forwarded.
can be found at: https://github.com/chromium/chromium/blob/f18e79d901f56154f80eea1e2218544285e62623/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/resources/class-list.js#L13
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