Soru JavaScript neden bir diziyi ve bir değişkeni bir değişkende saklamanıza izin verir? [kapalı]


Bir oyunu programlarken hatayla bir gün karşılaştım:

var foo = function() { alert("Hello, World!"); }

foo[0] = "Zero";
foo[1] = "One";
foo[2] = "Two";
foo[3] = "Three";

foo(); // Alerts "Hello, World!"
alert(foo[2]); // Alerts "Two"

JavaScript bunu neden yapmanıza izin veriyor? Bu bir aksaklık mı?


25
2017-08-02 21:05


Menşei


Sorunuz, bunun bir çeşit sorun olduğunu hissetmenizi gerektiriyor: sorabilir miyim niye yaçünkü soruna ilk cevabım temel olarak neden olmasın? - David Thomas
Fonksiyonlar nesnelerdir. Nesnelerin özellikleri olabilir, bu yüzden foo.bar = "baz" yasaldır. Javascript, nesnelerdeki özelliklerine erişmek için iki yönteme sahiptir: nokta gösterimi ve parantez-gösterimi. Sonunu kullanıyorsun. - Waleed Khan
@DavidThomas Bu bir sorun değil. Bunun normal bir JavaScript davranışı olup olmadığını merak ediyordum. Aslında oldukça yararlı olabilir. - Luc
@LucTheRedstoner: "Aslında oldukça yararlı olabilir." Evet o çok işe yarar. :-) - T.J. Crowder
"Neden" yok. Sadece JavaScript var. - Chris Martin


Cevaplar:


Burada diziler yok. Örneğin, Array.isArray(foo) yanlış.

Bunun yerine foo dört özellik, adlandırılmış "0", "1", "2", ve "3" [1], farklı değerler ile. Bu tamamen geçerlidir, çünkü işlevler nesnelerdir; Nesneye istediğiniz gibi adlar ekleyerek her zaman özellik ekleyebilirsiniz.

Ayrıca şunları da yapabilirsiniz:

foo.otherProp = "hi!";

alert(foo.otherProp);

[1]: Özellik adlarının, bunları ayarlamadan önce her zaman dizeye dönüştürüldüğünü unutmayın; iş foo[{ toString: function () { return "baz"; }] = 5 ile aynı olacak foo["baz"] = 5 veya foo.baz = 5. Benzer şekilde, yapıyor foo[0] = "whatever" yapmakla aynı şey foo["0"] = "whatever".


37
2017-08-02 21:07



JS dönüştürüyor 0 üzerinde foo[0] için "0"  (Dize) yani foo[0] ve foo["0"] aynı, doğru Domenic? Burada konsolda test edildi ve öyle görünüyor. - RaphaelDDL
Evet, buna bir dipnot ekledim. - Domenic
@RaphaelDDL: Doğru. - T.J. Crowder
"Burada diziler yok." Bunun üzerine bir cevap açmak için mükemmel bir yol. Sadece mükemmel. - T.J. Crowder
Hata ayıklama yaparken ek bilgi: console.log üzerinde foo sadece döndürür function(). Hakkında tam bilgi için foo, kullan console.dir ve özellikler gösterilecektir. - RaphaelDDL


JavaScript neden bir diziyi ve bir değişkeni bir değişkende saklamanıza izin verir?

Olmaz. Değişkendeki bir işleve bir başvuru kaydetmenize izin verir. İşlevler, JavaScript'teki birinci sınıf nesnelerdir ve böylece, "0", "1", vb.

Burada birkaç şey görüyorsun:

  1. Yukarıda söylediğim, işlevler nesneler ve bunlara özellikler ekleyebilirsiniz.

  2. Ad-hoc özellikler ekleyebilirsiniz, bunları diğer dillerde olduğu gibi önceden tanımlamanıza gerek yoktur.

  3. JavaScript'te, nokta notasyonu ve bir literal kullanarak bir mülke başvurabilirsiniz.foo.bar)veya parantezli notasyon ve bir dize (foo["bar"]).

  4. Parantezli notasyon kullandığınızda, parantez içindeki şey zaten bir değilse bir dizeye gönderilir, yani [0] aslında ["0"].

Ve evet, bu son, dizilerle uğraşırken bile geçerli, çünkü standart JavaScript dizileri gerçekten diziler değildir. (Son eklenenler var, Int32Array ve bunlar gerçek dizilerdir, ancak Array değil.)


9
2017-08-02 21:08



Kaldırılan cümle, bir değişkene ait bir diziye atıfta bulunmaktan bahseder, çünkü bu kafa karıştırıcı ve potansiyel olarak yanıltıcı görünüyordu. Şimdi biraz kötü hissediyorum, muhtemelen sadece yorum yapmalı ve kendin yapmana izin vermeliydim, pardon. - Domenic
@Domenic: Teşekkürler, ama sadece bir yazım hatası ("function" anlamına geldiği "dizi"). - T.J. Crowder
Bu, bu kod parçasında devam eden tüm farklı şeylerin güzel bir şekilde ayrılmasını sağlar. +1 - Domenic


Cevap oldukça basittir ve bir dillogizm olarak ifade edilebilir (benim eğlencem için).

Tüm nesneler geliştirici tanımlı özelliklere sahip olabilir1.
Tüm işlevler nesnelerdir.
Bu nedenle, tüm işlevler geliştirici tanımlı özelliklere sahip olabilir.


1 Teknik olarak değil herşey nesneler. "Sertleştirilmiş" nesneler, güvenilmeyen kod tarafından dönüştürülemez ve JavaScript çalışma zamanını katıştıran uygulama tarafından sağlanan nesneler, bunu önlemek için davranışlarını özelleştirebilir. Bunlar olsa da, kenar vakaları. JavaScript çalışma zamanının içinden oluşturulan sertleştirilmemiş nesnelerin tümü bu işlevselliği sergilemelidir ve çoğu zaman bunların değişmeye çalıştığı nesnelerdir.


4
2017-08-02 21:08





foo[0] bu durumda değeri "0" adlı bir özelliğe atar. Bir işlev bir nesnedir ve ona eklenmiş özelliklere sahip olabilir.

Aynı şekilde, bu ikisi eşittir:

foo["abc"]
foo.abc

3
2017-08-02 21:08





Javascript’teki hemen hemen her şey (fonksiyonlar dahil) bir nesnedir. 0 ve 1.


0
2017-08-02 21:07



Bu doğru değil: 5 bir nesne değildir. Deneyin: 5.foo = "bar"; alert(5.foo);. Aynı şey diğer tüm ilkeller için de geçerlidir. Bir şey bir nesne ise genel test olup olmadığıdır. Object(thing) === thing. - Domenic
@Domenic: Doğru, ama aslında, ilkel bir nesneye terfi ettirilir (veya sözdizimi işlenirse, örn. (5).foo = "bar"; olmadan ()  . ondalık noktaya benziyor), ona bir özellik eklenir ve sonra bu nesne atılır. (Bütün sebep budur "string".anyMethodHere() çalışır.) olduğu çok geniş, ama çok değil. :-) - T.J. Crowder
@Domenic @ T.J.Crowder'ın söylediklerine ek olarak, ayrıca 5..foo = 'bar';. İlk nokta bir ondalık nokta olarak yorumlanır ve ikincisi mülk erişimi olarak yorumlanır - Daniel Lo Nigro
Evet; Bu hiçbiri benim yorumumda söylediğimi değiştirmez. - Domenic


Her şeyden önce, sorunuzun başlığınızla ilgisi yoktur.

Başlığınızda sorulan soruya verilen yanıt, "JavaScript bir diziyi ve bir değişkeni bir değişkende saklamanıza neden izin veriyor?", JavaScript bir dinamik yazılan dil ve bu, bir değişkendeki neyi istediğinizi koyabileceğiniz ve tercümanın şikayet etmeyeceği anlamına gelir.

Sorunuzun gövdesinde, bir nesnenin veya bir dizinin sanki bir işlevin niteliklerini neden belirlemenize izin verildiğini merak ediyorsunuz.

Eh, sadece yapabilirsin. Bu dilin tanımı. Bir fonksiyon hakkında meformasyon ekleyebilmek için çok faydalıdır.

Ama evet, JavaScript keskin kenarlar ve sivri uçlarla kaplıdır, bu yüzden dikkatli olmalısınız.


0
2017-08-02 21:11



First of all, your question has nothing to do with your title. - bu bizim için doğru olsa da, açıkçası OP için açık değildir, çünkü onlar bir dizi olarak işlev görüyorlardı (sayısal özellikler belirlendiğinden). Dinamik olarak yazılan JavaScript'in OP'in başlığıyla ilgisi yoktur - açıkçası değişkenin hem bir işlevi hem de diziyi tuttuğunu yanlış düşünmeye atıfta bulunurlar. Ve Well, you just can. That's the definition of the language. yararlı bir cevap değil - Ian


JavaScript'te işlevler birinci sınıftır nesneleri.

function foo() {}
var isObject = foo instanceof Object;
// isObject is true

Bu, bir değişkene işlevler atamak, bunları argüman olarak iletmek, işlevleri vb.

MDN referansı


0
2017-08-02 21:11





Şimdiye kadar hiç kimsenin bahsettiği şey, bu özelliğin, bilgiyi işlevsellik açısından yararlı olabilecek bir işlevle ilişkilendirmenize izin vermesidir; ancak, küresel alanı, çarpışmalar yaratabilecek çok sayıda ortak veriyle kirletmeden.

Bu elbette genel olarak bir OOP / prototipleme özelliğidir, fakat daha genel bir nesnenin bir özelliği olarak değil, doğrudan bir işlevi çağırmanıza izin vermenin ek yararına sahiptir.


0
2017-08-02 21:15