JavaScript Dünyasında Zorlama Var - Bir Dedektif Hikayesi
Nathan, neyi ortaya çıkardığına dair hiçbir fikrin yok.
Bunu haftalardır araştırıyorum. Her şey geçen Ekim ayında fırtınalı bir gecede başladı. Yanlışlıkla Numbersınıfa tökezledim - yani, dünyada neden JavaScript'in bir Numbersınıfı vardı?
Bundan sonra ne bulacağım için hazırlıklı değildim.
JavaScript'in size söylemeden, sayılarınızı nesnelere, nesnelerinizi de burnunuzun altındaki sayılara dönüştürdüğü ortaya çıkıyor.
JavaScript kimsenin yakalayamayacağını umuyordu, ancak insanlar garip beklenmedik davranışlar bildiriyorlar ve şimdi siz ve sorunuz sayesinde bu şeyi tamamen açmam için gereken kanıtlara sahibim.
Şimdiye kadar öğrendiğimiz şey bu. Size bunu söylemem gerekip gerekmediğini bilmiyorum - JavaScript'inizi kapatmak isteyebilirsiniz.
> function dis() { return this }
undefined
Bu işlevi oluşturduğunuzda, muhtemelen daha sonra ne olacağı hakkında hiçbir fikriniz yoktu. Her şey iyi görünüyordu ve her şey iyiydi - şimdilik.
Hata mesajı yok, sadece konsol çıktısında "undefined" kelimesi, tam olarak beklediğiniz gibi. Sonuçta, bu bir işlev beyanıydı - hiçbir şey döndürmemesi gerekiyordu.
Ama bu sadece başlangıçtı. Daha sonra ne olacağını kimse tahmin edemezdi.
> five = dis.call(5)
Number {[[PrimitiveValue]]: 5}
Evet biliyorum, bekledin 5ama, sahip olduğun şey bu değildi - başka bir şeyin var - farklı bir şey.
Aynı şey bana da oldu.
Ne yapacağımı bilmiyordum. Beni deli etti. Uyuyamadım, yiyemedim, içmeye çalıştım, ama hiçbir miktarda Dağ Çiy beni unutturmazdı. Hiç bir anlamı yoktu!
O zaman gerçekten neler olup bittiğini öğrendim - zorlama oldu ve tam gözlerimin önünde oluyordu, ama görmek için çok kördüm.
Mozilla, kimsenin görünmeyeceğini bildiği yere koyarak belgelerini gömmeye çalıştı .
Saatlerce tekrar tekrar okuma ve yeniden okuma ve tekrar okumadan sonra bunu buldum:
"... ve ilkel değerler nesnelere dönüştürülecek."
Open Sans yazı tipinde söylenebileceği gibi düz. O was call()fonksiyonu - bu kadar aptal nasıl olabilir ?!
Numaram artık bir sayı değildi. Onu geçirdiğim an call()başka bir şey oldu. Nesne oldu.
İlk başta inanamadım. Bu nasıl doğru olabilir? Ama etrafımdaki kanıtları görmezden gelemedim. Sadece bakarsanız tam orada:
> five.wtf = 'potato'
"potato"
> five.wtf
"potato"
wtfhaklıydı. Sayıların özel özellikleri olamaz - hepimiz bunu biliyoruz! Akademide size ilk öğrettikleri şey.
Konsol çıktısını gördüğümüz anı bilmeliydik - bu sandığımız sayı değildi. Bu bir sahtekârdı - kendini tatlı masum sayımız olarak gösteren bir nesne.
Bu oldu ... new Number(5).
Elbette! Mükemmel bir anlam ifade etti. call()yapması gereken bir işi vardı, bir işlevi çağırmak zorundaydı ve doldurmak için bunu yapmak zorundaydı, bunu thisbir sayı ile yapamayacağını biliyordu - bir nesneye ihtiyacı vardı ve bunu elde etmek için her şeyi yapmaya istekliydi, hatta bu numaramızı zorlamak anlamına geliyorsa. Ne zaman call()numarayı gördü 5, o bir fırsat gördü.
Mükemmel plan buydu: Kimse görünmeyene kadar bekleyin ve bizim gibi görünen bir nesne için numaramızı değiştirin. Bir sayı alırız, fonksiyon çağrılır ve kimse daha akıllıca olmaz.
Gerçekten mükemmel bir plandı, ama tüm planlar, hatta mükemmel olanlar gibi, içinde bir delik vardı ve biz de onun içine düşmek üzereydik.
Bakın, call()anlamayan şey, şehirde sayıları zorlayabilecek tek kişi o değildi. Sonuçta bu JavaScript'ti - baskı her yerdeydi.
call() numaramı aldım ve maskeyi küçük sahtekarından çıkarıp onu tüm Stack Overflow topluluğuna maruz bırakana kadar durmayacaktım.
Ama nasıl? Bir plana ihtiyacım vardı. Tabii ki bir sayı gibi görünüyor, ama biliyorum, bunu kanıtlamanın bir yolu olmalı. Bu kadar! Bu görünen bir sayı gibi, ancak biri gibi davranabilir?
five5 kat daha büyük olması için ona ihtiyacım olduğunu söyledim - nedenini sormadı ve açıklamamıştım. Sonra iyi bir programcının yapacağı şeyi yaptım: Çoğalttım. Elbette bundan kurtulmanın hiçbir yolu yoktu.
> five * 5
25
> five.wtf
'potato'
Lanet olsun! Sadece çarpmakla kalmadı, fivesadece wtforadaydı. Bu adama ve patatesine lanet olsun.
Neler oluyor? Bütün bunlar hakkında yanılmış mıydım? Mı fivebir numara gerçekten? Hayır, bir şey eksik olmalıyım, biliyorum, unutmam gereken bir şey var, çok basit ve basit bir şey var.
Bu iyi görünmüyordu, saatlerce bu cevabı yazıyordum ve hala benim açımdan daha yakın değildim. Bunu devam ettiremedim, sonunda insanlar okumayı bırakacaktı, bir şey düşünmek zorunda kaldım ve hızlı düşünmek zorunda kaldım.
Bekle bu! five25, 25 sonuç 25, tamamen farklı bir sayı oldu. Tabii ki, nasıl unutabilirim? Sayılar değişmez. Çarptığınızda5 * 5 hiçbir şey herhangi bir şeye atanmaz, sadece yeni bir sayı oluşturur 25.
Burada olan bu olmalı. Bir şekilde çarptığımda five * 5, fivebir sayıya zorlanıyor olmalı ve bu sayı çarpma için kullanılan sayı olmalıdır. Konsolda yazdırılan çarpımın sonuçları, fivekendisinin değeri değil .fiveasla bir şey atanmaz - bu yüzden elbette değişmez.
Öyleyse fivebir operasyonun sonucunu nasıl atayabilirim? Anladım. fiveDüşünme şansım bile olmadan , "++" diye bağırdım.
> five++
5
Aha! Ona sahiptim! Herkes bilir 5 + 1olduğunu 6bu Bunu açığa çıkarmak için gerekli kanıtı olduğunu, fivesayı değildi! Bir sahtekârdı! Nasıl sayılacağını bilmeyen kötü bir sahtekâr. Ve kanıtlayabilirim. Gerçek bir sayının işleyişi şöyle:
> num = 5
5
> num++
5
Bekle? Burada ne oluyordu? iç çekerek öylesine yakalandım fiveki post operatörlerin nasıl çalıştığını unutuyorum. Ben kullandığım ++sonunda fiveben geçerli değeri döndürmek, sonra artış kullanın five. Bu değer daha önce operasyon konsola basılmış olur o gerçekleşir. numaslında 6ve bunu kanıtlayabilirim:
>num
6
fiveGerçekte ne olduğunu görme zamanı :
>five
6
... olması gereken şey buydu. fiveiyiydi - ama daha iyiydim. Eğer fivehala hala özelliği olurdu anlamına gelecektir bir nesne vardı wtfve ben etmedi bahis her şey hazırdı.
> five.wtf
undefined
Aha! Haklıydım. Ona sahiptim! fiveartık bir sayıydı - artık bir nesne değildi. Çarpma numarasının bu sefer onu kurtaramayacağını biliyordum. five++Gerçekten bakın five = five + 1. Çarpmanın aksine, ++operatör bir değer atar five. Daha spesifik olarak, five + 1çarpma durumunda olduğu gibi yeni bir değişmez sayı döndürdüğü sonuçları atar. .
Ona sahip olduğumu biliyordum ve sadece onun yolunu kıramayacağından emin olmak için. Kolumda bir test daha yaptım. Eğer haklıysam ve fiveşimdi gerçekten bir numara olsaydım, bu işe yaramazdı:
> five.wtf = 'potato?'
'potato?'
Bu sefer beni kandırmayacaktı. potato?Konsola yazdırılacağını biliyordum çünkü ödevin çıktısı bu. Asıl soru, wtfhala orada olacak mı?
> five.wtf
undefined
Şüphelendiğim gibi - hiçbir şey - çünkü sayılara özellik atanamaz. Akademide ilk yılı öğrendik;)
Teşekkürler Nathan. Bu soruyu sorma cesaretiniz sayesinde nihayet bütün bunları arkamda bırakabilir ve yeni bir davaya geçebilirim.
Bunun gibi işlev hakkında toValue(). Ah tanrım. Nooo!
++altta yatan türü etkiliyor gibi görünüyor