У світі JavaScript є примус - історія детектива
Натане, ти поняття не маєш, що ти розкрив.
Я розслідую це вже тижнями. Все почалося у бурхливу ніч у жовтні минулого року. Я випадково натрапив на Numberклас - я маю на увазі, чому в світі у JavaScript був Numberклас?
Я не був готовий до того, що збирався дізнатися далі.
Виявляється, JavaScript, не розповідаючи, міняв ваші номери на об'єкти, а ваші об'єкти на номери прямо під носом.
JavaScript сподівався, що ніхто не піде назустріч, але люди повідомляють про дивну несподівану поведінку, і тепер завдяки вам і вашому запитанню я маю докази, що мені потрібно роздути цю річ.
Це ми дізналися поки що. Я не знаю, чи варто мені це навіть розповідати - ви можете вимкнути JavaScript.
> function dis() { return this }
undefined
Коли ви створили цю функцію, ви, мабуть, не мали уявлення, що буде далі. Все виглядало нормально, і все було добре - поки що.
Немає повідомлень про помилки, лише слово "невизначено" у виведенні консолі, саме те, що ви очікували. Зрештою, це була декларація функції - вона нічого не повинна повертати.
Але це було лише початком. Що сталося далі, ніхто не міг передбачити.
> five = dis.call(5)
Number {[[PrimitiveValue]]: 5}
Так, я знаю, ви очікували 5, але це не те, що ви отримали, це було - у вас щось інше - щось інше.
Те саме трапилось і зі мною.
Я не знав, що з цього зробити. Це ганяло мене. Я не міг спати, не міг їсти, я намагався його випити, але жодна кількість гірської роси не змусила мене забути. Це просто не мало сенсу!
Ось тоді я дізнався, що насправді відбувається - це був примус, і це відбувалося прямо там перед моїми очима, але я був занадто сліпий, щоб бачити це.
Мозілла спробувала поховати його, поклавши там, де вони знали, що ніхто не шукатиме - їх документацію .
Після годин рекурсивного читання та перечитування та перечитування я виявив таке:
"... і примітивні значення будуть перетворені на об'єкти."
Це було прямо там, як це просто написано шрифтом Open Sans. Це була call()функція - як я можу бути таким дурним ?!
Мій номер уже не був номером. Щойно я передавав це call(), це стало чимось іншим. Це стало ... об’єктом.
Я не міг спочатку повірити. Як це могло бути правдою? Але я не міг ігнорувати докази, які збиралися навколо мене. Це прямо там, якщо ви просто подивіться:
> five.wtf = 'potato'
"potato"
> five.wtf
"potato"
wtfбув правий. Цифри не можуть мати власні властивості - ми всі це знаємо! Це перше, чого вони навчають тебе в академії.
Ми повинні були знати, коли ми побачили вихід консолі - це не та цифра, яку ми думали. Це був самозванець - предмет, що передається як наш солодкий невинний номер.
Це було ... new Number(5).
Звичайно! Це мало ідеальний сенс. call()він повинен був виконувати роботу, він повинен був викликати функцію, і для цього йому потрібно було заселити this, він знав, що не може цього зробити з числом - йому потрібен предмет і він був готовий зробити все, щоб його отримати, навіть якщо це означало примусити нашу кількість. Коли call()побачив номер 5, він побачив можливість.
Це був ідеальний план: зачекайте, поки ніхто не шукає, і поміняйте нам номер на предмет, який виглядає так само. Ми отримуємо число, функція викликається, і ніхто не буде мудрішим.
Це справді був ідеальний план, але, як і всі плани, навіть ідеальні, в ньому була дірка, і ми ось-ось впали прямо в неї.
Бачите, що call()не зрозумів, що він не єдиний у місті, який міг примусити число. Зрештою, це був JavaScript - примус був скрізь.
call() взяв свій номер, і я не збирався зупинятися, поки не зняв маску свого маленького самозванця і не виставив його всій спільноті Stack Overflow.
Але як? Мені потрібен був план. Звичайно, це схоже на число, але я знаю, що це не так, має бути спосіб довести це. Це воно! Це схоже на число, але чи може воно діяти як одне?
Я сказав, що fiveмені потрібно, щоб він став у 5 разів більшим - він не запитував, чому, і я не пояснив. Тоді я зробив те, що зробив би будь-який хороший програміст: я примножив. Звичайно, не було способу підробити вихід із цього.
> five * 5
25
> five.wtf
'potato'
Блін! Не тільки fiveрозмножувалося, просто чудово wtfбуло ще. Чорт цей хлопець та його картопля.
Що за чорт сталося? Чи помилявся я у всьому цьому? Це fiveдійсно число? Ні, я, мабуть, щось пропускаю, я це знаю, є щось, що я мушу забути, щось таке просте і базове, що я повністю його не помічаю.
Це виглядало не дуже добре, я писав цю відповідь годинами і все ще не ближче до висловлення своєї думки. Я не міг продовжувати це, з часом люди перестали читати, мені довелося щось придумати, і мені довелося швидко подумати про це.
Зачекайте, це все! fiveНе було 25, 25 - результат, 25 - зовсім інше число. Звичайно, як я міг забути? Числа незмінні. Коли ви множите, 5 * 5нічого не призначається нічому, ви просто створите нове число 25.
Це повинно бути, що відбувається тут. Якось, коли я множу five * 5, fiveтреба примушуватися до числа, і це число повинно бути тим, яке використовується для множення. Це результати того множення, яке друкується на консолі, а не саме значення five. fiveніколи нічого не присвоюють - тому, звичайно, це не змінюється.
Тож як мені змусити fiveпризначити собі результат операції. Зрозумів. Перш ніж fiveнавіть був шанс подумати, я закричав "++".
> five++
5
Ага! Я мав його! Кожен знає 5 + 1це 6, це було доказом мені потрібно було виставити , що fiveне було поруч! Це був самозванець! Поганий самозванець, який не вмів рахувати. І я міг це довести. Ось як діє реальна кількість:
> num = 5
5
> num++
5
Чекати? Що тут було? зітхання Я настільки захопився перебоями, fiveщо забув, як працюють поштові оператори. Коли я використовую ++в кінці слова, fiveя кажу повернути поточне значення, а потім приріст five. Це значення перед початком операції надрукується на консолі. numбуло насправді, 6і я міг це довести:
>num
6
Час подивитися, що fiveнасправді було:
>five
6
... це було саме те, що має бути. fiveбуло добре - але я був кращим. Якби fiveвсе-таки був об’єкт, це означало б, що він все-таки матиме власність, wtfі я був готовий зробити ставку на все, чого він не робив.
> five.wtf
undefined
Ага! Я був правий. Я мав його! fiveтепер було числом - це вже не об’єкт. Я знав, що фокус на множення не врятує цього разу. Бачити five++- це справді five = five + 1. На відміну від множення, ++оператор присвоює значення five. Більш конкретно, він присвоює їй результати, five + 1як і у випадку множення, повертає нове незмінне число .
Я знав, що маю його, і просто переконався, що він не зможе вирватися з нього. У мене був ще один тест на рукаві. Якби я мав рацію, і зараз fiveбув справді чисельним, то це не працювало б:
> five.wtf = 'potato?'
'potato?'
Цього разу він не збирався мене обманювати. Я знав, potato?що буде надрукований на консоль, тому що це результат завдання. Справжнє питання, чи wtfвсе ще буде там?
> five.wtf
undefined
Як я підозрював - нічого - тому що числам не можна присвоїти властивості. Ми дізналися, що перший рік в академії;)
Спасибі Натане. Завдяки вашій мужності в питанні цього питання я можу нарешті все це поставити за собою і перейти до нової справи.
Як і ця щодо функції toValue(). О боже мілий. Nooo!
++здається, впливає на базовий тип