HTML attributes और DOM properties के बीच अंतर
(jakearchibald.com)- एक ही element से जुड़े होने पर भी HTML attributes और DOM properties अलग-अलग storage space की तरह काम करते हैं, इसलिए एक में किया गया बदलाव अपने-आप दूसरे में reflect न हो सकता है
- attributes HTML serialization और developer tools के Elements panel में दिखते हैं, लेकिन properties सिर्फ DOM की state होती हैं, इसलिए
outerHTMLजैसे results में नहीं दिखतीं - attribute values हमेशा strings होती हैं और names case-sensitive नहीं होते, जबकि properties के पास objects समेत कई तरह के types हो सकते हैं और उनके names case-sensitive होते हैं
id,className,htmlFor,ariaLabelजैसे attributes को reflect करने वाली properties होती हैं, जबकिinput.valueजैसे cases में current state और default setting अलग होती हैं- framework के हिसाब से target अलग होता है: Preact और VueJS आम तौर पर properties को, React आम तौर पर attributes को priority देता है, और Lit
.valuesyntax से दोनों को explicitly अलग करता है
Attributes और properties का नाम समान हो, फिर भी वे अलग हो सकते हैं
- attributes और properties अलग-अलग storage space की तरह काम कर सकते हैं
- `` में
getAttribute('foo')'bar'return करता है, लेकिनdiv.fooundefinedहो सकता है - बाद में
div.foo = 'hello world'set करने पर भीfooattribute value'bar'ही रहती है
- `` में
- framework templates में `` जैसी attribute जैसी दिखने वाली syntax इस्तेमाल करने पर भी, internally कुछ cases में property set हो सकती है
- property कब set की जाती है, यह framework के हिसाब से अलग होता है
- कुछ settings property और attribute दोनों को बदलने वाला side effect बना सकती हैं
HTML serialization में attributes ही रहते हैं
- attributes HTML और DOM दोनों में मौजूद होते हैं, लेकिन properties सिर्फ DOM में मौजूद होती हैं
div.setAttribute('foo', 'bar')औरdiv.hello = 'world'दोनों run करने पर भीdiv.outerHTMLमें `
` की तरह सिर्फ attributes दिखते हैं
- browser developer tools का Elements panel element के attributes दिखाता है, सभी properties नहीं दिखाता
Value type और case handling
- attribute values serialized format में काम करनी होती हैं, इसलिए वे हमेशा strings होती हैं
- object को
setAttributeसे डालने पर वह string"[object Object]"के रूप में store होता है - वही object property में डालने पर object type वैसा ही बना रह सकता है
- object को
- attribute names case-sensitive नहीं होते
HeLlO="world"DOM मेंhelloattribute के रूप में normalize हो सकता हैsetAttribute('FOO', 'bar')भीfooattribute के रूप में दिखता है
- property names case-sensitive होते हैं
div.TeSt = 'value'set करने पर भीdiv.testundefinedहो सकता है
- attribute names के विपरीत, attribute values case-sensitive होती हैं
Attributes को reflect करने वाली properties
- कुछ properties किसी खास attribute को reflect करती हैं
div.ididattribute को पढ़ने और लिखने वाले getter/setter की तरह काम करता हैdiv.id = 'bar'run करने परidattribute भी'bar'में बदल जाता है
- reflection relationship में attribute data का source होता है
- property set करने पर attribute update होता है
- property read करने पर attribute value read होती है
- specification में defined attributes के लिए सुविधा के तौर पर corresponding property अक्सर बनाई जाती है
- arbitrary
fooattribute spec में defined attribute नहीं है, इसलिए correspondingfooproperty अपने-आप नहीं बनती
- arbitrary
- `` specification “Content attributes” में attributes और “DOM interface” में properties define करता है
reversedऔरtypeIDL attributes को उसी नाम के content attributes को reflect करना चाहिए
Reflection relationship में नाम बदल जाना
- कुछ properties का नाम उस attribute से अलग होता है जिसे वे reflect करती हैं
- JavaScript property style से match करने के लिए नाम बदलने के cases होते हैं
- `` का
el.crossOrigin,crossoriginattribute को reflect करता है - सभी elements का
el.ariaLabel,aria-labelattribute को reflect करता है - ARIA reflection properties 2023 के अंत में cross-browser बनीं; उससे पहले केवल attributes इस्तेमाल किए जा सकते थे
- `` का
- पुराने JavaScript reserved words की वजह से भी नाम बदलने के cases हैं
- सभी elements का
el.className,classattribute को reflect करता है - `` का
el.htmlFor,forattribute को reflect करता है
- सभी elements का
Validation, type conversion, default values
- properties के साथ validation और default values जुड़ सकते हैं, लेकिन attributes में खुद ऐसा behavior नहीं होता
input.typeattribute और property के फर्क को अच्छी तरह दिखाता हैinput.getAttribute('type')nullहो तब भीinput.typedefault value'text'return करता हैinput.type = 'number'attributes और properties दोनों में'number'जैसा दिखता हैinput.type = 'foo'attribute में'foo'डालता है, लेकिन property getter invalid value देखकर'text'return करता है
- कुछ properties type conversion करती हैं
- `` में
details.getAttribute('open')empty string होता है औरdetails.opentrueहोता है details.open = falseopenattribute को remove कर देता हैdetails.open = 'hello'string को सीधे attribute में नहीं डालता, बल्कि boolean में convert करके ऐसी state बना देता है जिसमेंopenattribute मौजूद होता है
- `` में
img.heightजैसी properties attribute value को number में convert करती हैं- setter incoming value को number में बदलता है, और negative values को 0 के रूप में handle करता है
input.value current value और default value को अलग करता है
inputमेंvalueproperty औरvalueattribute दोनों होते हैं, लेकिनvaluepropertyvalueattribute को reflect नहीं करतीvalueattribute को reflect करने वाली propertydefaultValueहैdefaultValuegettervalueattribute या empty string return करता हैdefaultValuesettervalueattribute को string के रूप में set करता है
valueproperty शुरुआत मेंdefaultValueको follow करती है, लेकिन JavaScript या user interaction से set होने के बाद internal value इस्तेमाल करती है- शुरुआती `` में
value,defaultValue,getAttribute('value')सभी'default'होते हैं input.defaultValue = 'new default'run करने पर attribute औरvalueदोनों'new default'जैसे दिखते हैं- इसके बाद
input.value = 'hello!'run करने परvalue'hello!'हो जाता है, लेकिन attribute औरdefaultValue'new default'ही रहते हैं setAttribute('value', 'another new default')run करने पर भी currentvalue'hello!'ही रहता है
- शुरुआती `` में
- form reset होने पर internal
valuestate initialize होने के तरीके से काम कर सकती है
Attributes settings के लिए और properties state के लिए ज्यादा natural हैं
- attributes को configuration के लिए और properties को state के लिए इस्तेमाल करना natural distinction है
- `` नाम को छोड़ दें तो इस distinction से match करने वाला example है
valueattribute default value set करता हैvalueproperty current state provide करती है
- property read या write करते समय validation apply होना, और attribute read या write करते समय validation apply न होना भी इसी approach से match करता है
औरopen state कोopenattribute से express करते हैं, और browser user interaction के हिसाब से इस attribute को सीधे add या remove करता है- यह design attributes को settings के लिए मानने वाले distinction को तोड़ता है
- DOM maintain करने वाले frameworks या सामान्य JavaScript code को ऐसी स्थिति के लिए तैयार रहना पड़ता है जिसमें DOM खुद बदलता है
- alternative design को `` जैसे default setting attribute, current state read/write करने वाली
details.openproperty, और state targeting के लिए CSS pseudo-class में बांटा जा सकता है - Simon Peters ने इससे जुड़ी early design discussion ढूंढ निकाली
contenteditableभी इस distinction को तोड़ता है, लेकिन इसे कई breakages को accept करने वाले opt-in के रूप में treat किया जाता है
Frameworks के हिसाब से handling
- Preact और VueJS कुछ predefined exceptions को छोड़कर
propName in elementtrue होने पर property set करते हैं, और नहीं तो attribute set करते हैं- by default वे attributes से ज्यादा properties को prefer करते हैं
- string rendering methods उल्टा काम करते हैं, और property-only items को ignore करते हैं
- related implementations: Preact का
setProperty, VueJS काshouldSetAsProp
- React कुछ predefined exceptions को छोड़कर attribute set करता है
- यह approach string rendering methods जैसी logic बनाता है
- custom elements की properties React की predefined list में नहीं होतीं, इसलिए वे attributes के रूप में set होती हैं, और property-only APIs काम न कर सकती हैं
- React 19 में custom elements के लिए Preact/VueJS model पर switch होने की योजना है
- React ने
classNameनाम की property को attribute जैसी दिखने वाली syntax के रूप में popular किया, लेकिन internallyclassattribute set करता है - related implementation: React का
setProp
- lit-html syntax में attributes और properties का फर्क बनाए रखता है
- `` की तरह name के आगे
.लगाने पर attribute नहीं, बल्कि property set होती है - related docs: Lit expressions
- `` की तरह name के आगे
3 टिप्पणियां
Hacker News की राय
data- attributes* का इस्तेमाल लेख में बताए गए तरीकों के बीच एक अच्छा समझौता बन जाता है
ये attributes JavaScript में
datasetकी read/write properties के रूप में अपने-आप expose हो जाते हैं, इसलिएdocument.getElementById('myDiv').dataset.payload == "something"की तरह access किए जा सकते हैंबस ध्यान रखना चाहिए कि HTML attributes
kebab-caseमें होते हैं और JavaScriptcamelCaseमें, इसलिएdata-my-cool-data-attributedataset.myCoolDataAttributeबन जाता हैcamelCaseइस्तेमाल करने वाले कई ecosystems में uppercase abbreviations को कैसे handle किया जाए, इसकी कोई स्थापित convention नहीं है, इसलिएdataset.myIDजैसे cases ambiguous हो जाते हैंkebab-caseऔरcamelCaseconversion से बचने के लिएElement.hasAttribute('data-thing'),Element.getAttribute('data-thing'),Element.setAttribute('data-thing', '...')जैसे methods इस्तेमाल करता/करती हूँDOM में inspect या debug करते समय अटपटा conversion नहीं करना पड़ता, इसलिए intent कहीं ज्यादा साफ रहता है
साथ ही https://developer.mozilla.org/en-US/docs/Web/HTML/Global_att... में
data-*global attributes को “custom data attributes जो scripts को HTML और DOM representation के बीच अपनी जानकारी exchange करने देते हैं” के रूप में समझाया गया हैयहां context से मतलब जरूरी नहीं कि अलग-अलग
iframeहों; बल्कि browser extensions जैसी स्थितियां भी हैं, जहां उसी DOM को access करने वाले अलग JavaScript execution contexts बनाए जाते हैंdeveloper tools protocol की terminology में इन्हें isolated worlds भी कहा जाता है
लेख में जिन चीजों पर बात की गई है, वे ऐसी complexity और behavior दिखाती हैं जिनसे जीवन में कोई खास फायदा नहीं
ऐसे behavior में फायदे के बिना सिर्फ नुकसान हैं, और specification को बस DOM objects और JavaScript objects को एक ही चीज define करके attributes और properties को भी एक ही concept बना देना चाहिए था
DOM node में non-string values store कर पाना साफ तौर पर एक फायदा है, और इसे हल्के में टालने वाली बात नहीं है
जब तक आप यह demand नहीं करते कि सभी properties सिर्फ strings ही हो सकती हैं, यह बिल्कुल simple नहीं है
numbers के साथ conversion, objects set कर सकने वाली properties, और ऐसे properties जिनका attributes से कोई mapping नहीं है—सब consider करना पड़ेगा
फिर भी अगर 100% fixed convention या rule होता तो बेहतर होता, लेकिन यह आसान काम नहीं है
addEventListenerजैसे methods individual DOM elements की prototype properties हैं, लेकिन string attribute के रूप में देखें तो उनका कोई मतलब नहीं बनतातब DOM element methods को
HTMLElement.addEventListener(foo, 'some-event', e => console.log(e));जैसी free functions बनना पड़ेगा; यह taste की बात है, फिर भी JavaScript में object method calls इस्तेमाल कर पाना बेहतर लगता हैDOM elements के पास
setAttributeसे state बदलने वाला बहुत specific interface है, और जब उस interface के जरिए DOM को message भेजने के लिए बनाए गए JavaScript object पर सिर्फ property जोड़ दी जाए, तो उसे automatically route होने की उम्मीद क्यों करनी चाहिए—यह सवाल हैऐसा API बेहतर experience दे सकता है, लेकिन इसमें कुछ मुश्किलें हैं, और फिर भी शायद यह ज्यादा साफ-सुथरा होगा
शायद backend code बहुत लंबे समय तक लिखने की वजह से, ऐसे interfaces को देखकर लगता है कि अंदर बहुत अजीब चीजें चल रही हैं, और अतीत के किसी मददगार developer ने जितना संभव हो उतना safe wrapper दे दिया है
समझने में मददगार नजरिया यह है कि संकीर्ण अर्थ में attribute एक DOM node, यानी
Attrnode हैइस node में
name,value,ownerElement,prefixजैसी properties हो सकती हैं, और पूरे रूप में इसे array नहीं बल्किNamedNodeMapके रूप में owning element कीattributesproperty value से access किया जा सकता हैइसलिए
getAttribute(name)नाम misleading है; वास्तव में यह attribute node खुद नहीं, बल्कि उस attribute node कीvalueproperty return करता है, इसलिए यहgetAttributeValue(name)के ज्यादा करीब हैसंदर्भ: https://developer.mozilla.org/en-US/docs/Web/API/Element/get..., https://developer.mozilla.org/en-US/docs/Web/API/Element/get..., https://developer.mozilla.org/en-US/docs/Web/API/Attr
setAttribute,getAttribute,getAttributeNames,hasAttributeसे न हो सकने वाला और attribute node याel.attributesसे ही हो सकने वाला कोई practical काम है या नहींattribute nodes को elements के बीच move भी नहीं किया जा सकता, और element के अंदर attribute nodes का order भी नहीं बदला जा सकता
Jake, तो इसका क्या करें: https://jakearchibald.com/2023/against-self-closing-tags-in-...
properties को अपडेट न करने वाली दलील समझ आती है, लेकिन CSS से target कर पाना उपयोगी है
:checkedकी तरह एक pseudo-class भी होना चाहिएdebugger से गुजरने के बजाय DOM को तुरंत देख पाना debugging के लिए कहीं आसान है
शायद सबसे अहम फर्क persistence है, जिसे लेख में नहीं कवर किया गया
attributes तब तक बनी रहती हैं जब तक उस DOM tree के उसी root object तक access संभव है, जैसे page छोड़े बिना
object properties सिर्फ तब तक रहती हैं जब तक वह object garbage collection में नहीं चला जाता
अगर DOM node clone हो जाए या serialize/deserialize से गुजरे, तो वह वही attributes रखने वाला पूरी तरह अलग DOM node बन जाता है, इसलिए उसमें दूसरे node की non-default properties नहीं होंगी
दिलचस्प लेख है
JavaScript के DOM elements को हमेशा एक तरह के proxy की तरह देखा है
वे वास्तविक DOM element पर काम करने देते हैं, लेकिन साथ ही वे बस JavaScript objects भी हैं, इसलिए वास्तविक element से interact करने वाले functions इस्तेमाल करने के अलावा values assign करके मनचाहा काम किया जा सकता है—ऐसा लगता था
examples के साथ अच्छी तरह समझाया गया है और पढ़ने में अच्छा है; खासकर कई ऐसी details हैं जो अक्सर छूट जाती हैं, इसलिए यह कई लोगों के लिए मददगार हो सकता है
DOM properties को IDL attributes भी कहा जाता है
spec writers के बाहर
IDL attributesकहने वाले लोग कम ही हैं, और दोनों को attributes कहना बहुत भ्रमित कर देता हैअच्छा लेख है, और यह सोचने पर मजबूर करता है कि बेहतर expression model कैसा दिखेगा
अगर HTML में string के अलावा भी attributes हो सकें, और उनकी value scoped
scripttag की local value को reference करे, तो यह दिलचस्प होगाattributes को default settings के रूप में देखना थोड़ा अजीब लगा
उदाहरण के लिए अगर
classattribute सिर्फ default value दिखाए, तो classes toggle करते समय DOM inspector या stringified HTML में active class न दिखे, या inactive class दिखे—यह काफी अजीब होगाclassattribute इस system में ठीक से काम करता हैdocument का owner होने के नाते मैं
classattribute set करता हूं, और समय के साथ उस setting को बदल सकता हूं, लेकिन यह सिर्फ मैं करता हूंकिसी alternative system में browser hover या focus state पर react करके खुद classes add/remove करता, लेकिन शुक्र है ऐसा नहीं होता और pseudo-classes इस्तेमाल होती हैं
https://emewjin.github.io/html attribute (Attributes) और DOM property (Properties) के बीच का अंतर
लगता है attribute और property दोनों का अनुवाद एक ही "गुण" के रूप में कर दिया गया है..