2008-09-23 20 views
27

John Resig'in mükemmel Advanced javascript tutorial'dan geçiyorum ve aşağıdaki çağrılar arasındaki farkın ne olduğunu iyice anlayamıyorum: ('arguments' in yerleşik bir javascript sözcüğü olduğunu lütfen unutmayın tam olarak değil bir dizi dolayısıylaArray.slice ve Array(). Arasındaki fark

>>> arguments 
[3, 1, 2, 3] 
>>> Array.slice.call(arguments) 
3,1,2,3 0=3 1=1 2=2 3=3 
>>> Array.slice.call(arguments, 1) 
[] 
>>> Array().slice.call(arguments) 
3,1,2,3 0=3 1=1 2=2 3=3 
>>> Array().slice.call(arguments, 1) 
1,2,3 0=1 1=2 2=3 

Temelde benim yanlış anlama Array.slice ve Array(). dilim arasındaki fark aşağı kaynar) basitçe çağıran arguments.slice yerine Array.slice ile hack. Bu ikisi arasındaki fark tam olarak nedir ve neden Array.slice.call beklendiği gibi davranmıyor? (argümanlar listesinin ilk öğesinin tümünü geri veriyor).

cevap

38

Pek. .

>>> String.substring.call("foo", 1) 
"1" 

>>> String().substring.call("foo", 1) 
"oo" 

Array.slice şudur: ve dize() substring.call ("foo", 2) (1, "foo") String.substring.call çağırdığınızda

İzle ne olur Ne, Array prototipine eklenmiş dilim işlevine ya da herhangi bir örneklenmiş Array örneğine (Array() veya [] gibi) eklenmiş dilim işlevine düzgün şekilde başvurmaz.

Array.slice öğesinin hiç de boş olmadığı gerçeği, nesnenin (/ function/constructor) kendisinin yanlış uygulanmasıdır. Eşdeğer kodu IE'de çalıştırmayı deneyin ve Array.slice dosyasının null olduğu bir hatayla karşılaşırsınız.

Bu nedenle Array.slice düzgün davranmıyor (String.substring).

Kanıtı (aşağıdaki sadece alt dize gibi bir dilim (tanımına dayalı bekliyoruz asla bir şey) ...() üzerindedir): düzgün dilim ararsanız, Şimdi

>>> Array.slice.call([1,2], [3,4]) 
3,4 

() üzerinde ya bir örneği nesne veya Dizi prototip, size beklediğiniz alırsınız:

>>> Array.prototype.slice.call([4,5], 1) 
[5] 
>>> Array().slice.call([4,5], 1) 
[5] 

fazla kanıt ...

>>> Array.prototype.slice == Array().slice 
true 
>>> Array.slice == Array().slice 
false 
+0

o '08 tarayıcılarda nasıl davrandığını bilmiyorum, ancak erken 2013 itibariyle, 'String.substring.call' (' String' yapıcısı bir 'substring' özelliği olmadığı için) Chrome'da bir TypeError atar . – bfavaretto

+0

@bfavaretto, Firefox (tek başına) Array.slice' ve 'String.substring' komutunu uygular. Asker şüphesiz bunu denerken Firefox kullanıyordu. –

+0

Bilgi için teşekkürler @NathanWall. Firefox’un oldukça tuhafı, muhtemelen String.prototype.substring' ve ark’a kısayol olarak ekledikleri bir şey. geriye dönük uyumluluk için ... ve görünüşe göre bir süredir etrafta dolaşıyor. – bfavaretto

6

Dizi, yalnızca bir işlev olsa da (dizileri başlatmak için kullanılır) özel bir işlevdir. Array.slice, Array prototipindeki dilim() işlevine bir başvurudır. Sadece bir dizi nesnesinde çağrılabilir ve Konstrüktör (yani Array) üzerinde değil. Array() boş bir dizi döndürdüğü için, dizi özel davranıyor gibi görünüyor. Bu yerleşik olmayan Kurucu işlevleri için işe yaramaz gibi görünüyor (orada yeni kullanmak zorunda). Yani

Array().slice.call 

[].slice.call 
-1

Benim tahminim Array() gerçek bir dizi nesnesi iken Array bir prototiptir. JavaScript yorumuna bağlı olarak, yerleşik bir nesne tipinin prototip yöntemini doğrudan çağırmak işe yarayabilir veya olmayabilir. Spekülasyonun çalışması gerektiğine inandığını, sadece bir nesne üzerinde çalıştığını söylemiyorum.

0

Ben Dizisi tipi ve Array() yapıcı işlevi olduğunu düşünüyoruz.

FireBug etrafında Messing:

>>> Array === Array() 
false 

>>> Array.constructor 
Function() 

>>> Array().constructor 
Array() 
1

Nasıl herhangi bir arama beslenmiyor bir bağlam parametresi beri verilen örneklerde çalışma) (slice.call etmektir? Dilim kendi çağrı yöntemini uygular, böylece JavaScript'in çağrı yöntemini geçersiz kılar mı? Çağrılar ve başvuru yöntemleri, ilk parametreye, nesneyi çağırma için geçerli olan bağlamı (bu) nesnesini belirleyen bir nesne olarak alır.