Kimliğine sahip DOM ağacı öğeleri genel değişkenler haline geliyor mu?


364

Basit bir HTMLElement sarmalayıcısı için bir fikir üzerinde çalışarak Internet Explorer ve Chrome için aşağıdakileri tökezledim :

DOM ağacında kimliğe sahip belirli bir HTMLElement için div değişkenini ID olarak kullanarak div almak mümkündür. Yani bir div için

<div id="example">some text</div>

içinde Internet Explorer 8 ve Chrome Yapabileceğiniz:

alert(example.innerHTML); //=> 'some text'

veya

alert(window['example'].innerHTML); //=> 'some text'

Peki bu , DOM ağacındaki her öğenin genel ad alanındaki bir değişkene dönüştürüldüğü anlamına mı geliyor? Ayrıca, getElementByIdbu tarayıcılarda bu yöntemin yerine kullanılabilir mi?



1
@Bergi, şimdi bunu eski ve hatta geçersiz bunu belirtmez. Bu nedenle, bu özelliği kullanmamak için somut bir neden bulamıyorum.
ESR

@EdmundReed Bağlantılı sorunun cevabını tekrar okumak isteyebilirsiniz - bu hala kötü bir fikirdir: " örtük olarak beyan edilen global değişkenler " hiçbir takım desteğine sahip değildir ve " kırılgan koda yol açar ". Buna "özellik" demeyin, aşağıdaki cevap, uyumluluk nedenleriyle standardın bir parçası haline gelen bir hatanın nasıl olduğunu açıklar.
Bergi

1
@Bergi yeterince adil, haklısın. Yine de gerçekten düzgün bir özellik olduğunu düşünüyorum ve sadece sorunlu olduğu düşünülüyor çünkü insanlar bunun farkında değil. Bunu nasıl öngördüğümü: codepen.io/esr360/pen/WEavGE?editors=1000#0
ESR

@EdmundReed İçeriği ve mantığı doğru bir şekilde ayırmazsanız daha az sorunludur. Ayrıca, ad satırları olarak kötüye kullanan DOM öğelerine hiçbir zaman satır içi olay işleyicileri kullanmamanızı veya özel yöntemler yüklemenizi öneririm ("kapsam" olmadığını unutmayın).
Bergi

Yanıtlar:


395

Gerçekleşmesi gereken şey, 'adlandırılmış elemanlar'ın documentnesnenin görünür özellikleri olarak eklenmiş olmasıdır . Bu gerçekten kötü bir fikir, çünkü eleman isimlerinin gerçek özellikleri ile çatışmasına izin veriyor document.

IE, windownesnenin özellikleri olarak adlandırılmış öğeler de ekleyerek durumu daha da kötüleştirdi . Bu, iki kez kötüdür, çünkü artık öğelerinizi documentveya windownesnenin (veya projenizdeki herhangi bir kütüphane kodunun) herhangi bir üyesinden sonra kullanmak isteyebileceğiniz öğelerin adından kaçınmanız gerekir .

Ayrıca, bu öğelerin global benzeri değişkenler olarak görülebileceği anlamına gelir. Neyse ki bu durumda kodunuzdaki herhangi bir gerçek global varveya functionbildirim gölgelendirir, bu yüzden burada adlandırma konusunda çok endişelenmenize gerek yoktur, ancak çakışan bir adla küresel bir değişkene atama yapmaya çalışırsanız ve beyan etmeyi unutursanız o varda elemanın kendisine değer atamak için çalışır gibi, IE'deki bir hata alırsınız.

Genelde atlanması ve küresel olarak veya küresel varolarak görünür olan adlandırılmış öğelere güvenilmesi kötü bir uygulama olarak kabul edilir window. Stick document.getElementByIddaha yaygın destekli ve daha az belirsiz olduğu,. Yazmayı sevmiyorsanız, daha kısa bir adla önemsiz bir sarma işlevi yazabilirsiniz. Her iki durumda da, kimlikler arası arama önbelleği kullanmanın bir anlamı yoktur, çünkü tarayıcılar genellikle getElementByIdaramayı yine de hızlı bir arama kullanmak için optimize eder ; elde ettiğiniz tek şey öğeler değiştiğinde idveya belgeye eklendiğinde / belgeden kaldırıldığında ortaya çıkan sorunlardır .

Opera IE, ardından katıldı Webkit ve üzerinde adı unsurları koyma artık hem daha önce standartsız uygulama kopyalanan documentözellikleri ve bunları koyarak önceden IE sadece pratik windowolan varlık standardize olan yaklaşım belgeye ve her standardize HTML5 tarafından tarayıcı yazarları tarafından bize verilen kötü uygulama, onları sonsuza dek web'in bir parçası haline getirdi. Firefox 4 de bunu destekleyecek.

'Adlandırılmış öğeler' nedir? Bir Herhangi bir şey idbir ile ve bir şey name, formlar, resimler, çapalar ve birkaç başka ama değil diğer alakasız örnekler ise: amaçlarla 'tanımlamak' için kullanılan bir varlık nameformu giriş alanlarında kontrol isimler, parametre adları gibi öznitelik, <param>veya meta veri yazın <meta>. 'Tanımlama' name, lehine kaçınılması gerekenlerdir id.


5
Bu açık bir cevap, teşekkürler. Document.getElementById'yi atlamak benim fikrim değildi (aslında, bugünlerde element / element özelliklerini aramak için mümkün olduğunda xpath kullanıyorum). Adlandırılmış öğeler için bu (kötü) uygulamaya tökezledim ve nereden geldiğini merak ettim. Bunu yeterince cevapladınız; şimdi neden Chrome'da (webkit) de bulunabileceğini biliyoruz.
KooiInc

18
"Kullanımından namekaçınılmalıdır" istisnası <input>, nameözniteliğin form gönderimleri için anahtar / değer çiftlerinin anahtarını oluşturmada kritik bir rol oynadığı durumdur .
Yahel

7
FYI Firefox bunu sadece tuhaflık moduna alındığında yapar.
Crescent Fresh

4
@yahelc: yaptığım ayrım tam olarak bu. “ nameForm girdi alanlarında benzer kontrol adlarının diğer kullanımları değil ...”
bobince

13
NEDEN!? Bu deliliği durdurmak için yapabileceğimiz bir şey var mı? İşlevlerim öğelere yapılan göndermelerle yeniden tanımlandı ve hata ayıklamam bir saat sürdü. :(
Farzher

52

Önceki yanıtta belirtildiği gibi, bu davranış pencere nesnesinde adlandırılmış erişim olarak bilinir . Değeri namebazı elementler için öznitelik ve değeri idtüm elemanları için öznitelik küresel özellikleri olarak hazır windownesne. Bunlar adlandırılmış öğeler olarak bilinir. Yana windowtarayıcıda küresel nesne, her adlandırılmış eleman global değişken olarak erişilebilir olacaktır.

Bu, başlangıçta Internet Explorer tarafından eklenmiştir ve sonunda diğer tüm tarayıcılar tarafından yalnızca bu davranışa bağımlı sitelerle uyumluluk için uygulanmıştır. İlginçtir ki, Gecko (Firefox'un oluşturma motoru) bunu sadece tuhaflık modunda uygulamayı seçerken , diğer oluşturma motorları standart modda bıraktı.

Ancak, Firefox 14 itibariyle Firefox artık adlandırılmış erişimi destekler üzerinde windowstandartlar modunda nesne de. Bunu neden değiştirdiler? Standart modda bu işlevselliğe güvenen birçok site olduğu ortaya çıkıyor. Microsoft, bir pazarlama demosu bile yayınladı ve demonun Firefox'ta çalışmasını engelledi.

Webkit kısa bir süre önce tam tersi olduğunu düşünerek , windownesne üzerindeki adlandırılmış erişimi yalnızca tuhaflık moduna indirdi. Gecko ile aynı akıl yürütmeye karşı karar verdiler.

Yani… deli gibi göründüğü gibi, bu davranış artık standart moddaki tüm büyük tarayıcıların en son sürümünde kullanmak için teknik olarak güvenlidir . Ancak adlandırılmış erişim biraz uygun görünse de kullanılmamalıdır .

Neden? Bu makalede, küresel değişkenlerin neden kötü olduğu ile ilgili bir çok neden özetlenebilir . Basitçe söylemek gerekirse, bir sürü ekstra küresel değişkene sahip olmak daha fazla hataya yol açar. Diyelim ki yanlışlıkla adını yazın diyelim varve bir tip olur idDOM düğümü SÜRPRİZ ait!

Buna ek olarak, standartlaştırılmasına rağmen, tarayıcının adlandırılmış erişim uygulamalarında hala çok az tutarsızlık vardır.

  • IE hatalı namebiçimde öznitelik değerini form öğeleri (giriş, seçim vb.) İçin erişilebilir hale getirir .
  • Gecko ve Webkit yanlış <a>etiketlerin nameöznitelikleri üzerinden erişilebilir OLMADIĞI .
  • Gecko, aynı ada sahip birden çok adlandırılmış öğeyi yanlış işliyor (bir başvuru dizisi yerine tek bir düğüme başvuru döndürüyor).

Ve eminim kenar durumlarda adlandırılmış erişimi kullanmayı denerseniz daha fazlası vardır.

Diğer cevaplarda belirtildiği gibi document.getElementByIdbir DOM düğümüne onun tarafından bir referans almak için kullanın id. nameÖzniteliğini kullanarak bir düğüme başvuru almanız gerekiyorsa document.querySelectorAll.

Lütfen, lütfen sitenizde adlandırılmış erişim kullanarak bu sorunu yaymayın. Pek çok web geliştiricisi bu büyülü davranışı izlemeye çalışırken zaman kaybetti . Standart modda adlandırılmış erişimi kapatmak için gerçekten harekete geçmeli ve render motorları almalıyız. Kısa vadede bazı sitelerin kötü şeyler yapmasını engelleyecek, ancak uzun vadede web'in ilerlemesine yardımcı olacaktır.

Eğer ilgileniyorsanız blogumda daha ayrıntılı konuşacağım - https://www.tjvantoll.com/2012/07/19/dom-element-references-as-global-variables/ .


3
Sadece "kullanılmamalıdır" öncül bariz uyarı için bir not. Yani, bir kod kovboyuysanız SADECE kullanılmamalıdır. " Kod kovboylar sadece bunun için gidin.
Jeremy Foster

5
@jeremyfoster "kod kovboy" kötü geliştirici-düşmanca uygulamaları kullanan ve yayılan biri anlamına gelmedikçe, kesinlikle katılmıyorum.
Patrick Roberts

2
İyi bir kovboyun işaretlerinden biri, birçok kişinin aynı fikirde olmamasıdır. Ama şimdi felsefi kovboy gibiyim ya da böyle bir şey.
Jeremy Foster

DOM'a erişirken document.querySelectorAllve onlara document.querySelectorerişirken daha fazla kişi kullanıyor olmalıdır . Bunu kullanmanın iyi önerisi için +1. Elemanlara seçici ile erişmek kesinlikle daha verimli bir süreçtir.
Travis J

20

Sen tutması gerektiğini getElementById(), örneğin bu gibi durumlarda:

document.getElementById('example').innerHTML

IE , genel ad alanındaki öğeleri name ve ID öznitelikleri karıştırmayı sever , bu yüzden elde etmeye çalıştığınız şey hakkında açık olmak en iyisidir.


3

Evet onlar yapar.

Chrome 55, Firefox 50, IE 11, IE Edge 14 ve Safari 10'da
aşağıdaki örnekle test edilmiştir :

<!DOCTYPE html>
<html>
<head>
</head>
<body>
  <div id="im_not_particularly_happy_with_that">
    Hello World!
  </div>
  <script>
    im_not_particularly_happy_with_that.innerText = 'Hello Internet!';
  </script>
  <!-- Looking at you W3 HTML5 spec group _ -->
</body>
</html>

http://jsbin.com/mahobinopa/edit?html,output


1
Ayrıca Opera'da. Ancak, bu sayfada ifade edilen bu mekanizmaya itirazın çok iyi olduğunu düşünüyorum.
ncmathsadist

1

Soru şu olmalıdır: "Sağlanan kimlikleri olan HTML Etiketleri küresel olarak erişilebilir DOM Öğeleri haline geliyor mu?"

Cevap Evet!

Bu şekilde çalışmak gerekiyordu ve bu yüzden kimlikler W3C tarafından başlamak için tanıtıldı: Ayrıştırılmış bir komut dosyası ortamındaki bir HTML Etiketinin kimliği, karşılık gelen DOM Öğesi tanıtıcısı haline gelir.

Bununla birlikte, Netscape Mozilla, W3C'ye uymayı reddetti ve inatçı bir şekilde tahribatlı Ad özniteliğini kullanarak tahribat yarattı ve bu nedenle Komut Dosyası işlevselliğini ve W3C'nin Benzersiz Kimlikler'i tanıtmasının getirdiği kodlama kolaylığını kırdı.

Netscape Navigator 4.7 fiyasko sonrasında geliştiricilerinin hepsi gitti ve W3C'ye sızdı, oysa ortakları Web'i yanlış uygulamalar ve yanlış kullanım örnekleri ile değiştirdi. Belirli olmayan DOM öğelerine erişmek için kimlik tanıtıcılarını kullanan komut dosyalarının basitçe kırılması için, zaten kullanılmayan Ad özniteliğinin [!

Ayrıca , en azından verimsiz hale getirmek ve basitçe kırmadığı takdirde tarayıcıya daha fazla yük vermek document.all.ElementID.propertyyerine, kapsamlı kodlama dersleri ve örnekleri [tarayıcıları zaten tanımayacaktı] yazıp yayınlayacakları gibi yaptılar ElementID.property. HTML alanı (şimdi [1996-97], kullanımdan kaldırıldı) Adı ve aynı belirteç değeri sağlayan standart kimlik özelliği için aynı belirteci kullanarak.

Onlar - o zamanlar - ezici cahil kod yazma amatörlerini, isimlerin ve kimliklerin pratikte aynı olduğu konusunda ikna etmeyi başardılar, ancak kimlik özelliği, eski Name özelliğinden daha kısa ve bayt tasarrufu sağlayan ve kodlayıcı için daha uygun. Tabii ki bir yalandı. Veya - onların yerine yayınlanmış HTML makalelerinde, Komut Dosyası altyapısı tarafından erişilebilmeleri için etiketlerinize hem Ad hem de Kimlik sağlamanız gerekeceğine ikna edici makaleler.

Mozaik Katiller [kodlanmış “Mozilla”] öylesine sinirlendiler ki "eğer düşersek İnternet de öyle" diye düşünüyorlardı.

Yükselen Microsoft - öylesine naifti ki, kullanımdan kaldırılmış ve silme Adı özelliği için işaretlenmeleri ve benzersiz bir Tanımlayıcı olan bir kimlikmiş gibi davranmaları gerektiğini düşündüler, böylece komut dosyası işlevselliğini bozmazlardı. kursiyerleri tarafından kodlanmış eski sayfalar. Ölümcül yanıldılar ...

Ve ID ile çakışan elemanların bir dizi koleksiyonunun geri döndürülmesi de bu kasıtlı insan yapımı soruna bir çözüm değildi. Aslında bütün amacı yendi.

Ve bu W3C'nin çirkinleşmesinin ve bize böyle aptallar vermesinin tek nedeni document.getElementByIdve beraberindeki rokoko goddamn sinir bozucu sözdizimi ... (...)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.