Вибачте за відповідь на більш старе запитання, але причина, що вам потрібна як невизначена, так і нульова, проста: у мові набору протоколу на основі прототипу ви повинні абсолютно розмежовувати "цей об'єкт не визначає значення для X" і "цей об'єкт говорить, що X є нічого / null / порожній ".
Без цієї можливості неможливо пройти ланцюжок прототипу, і тому спадкування не може працювати; ви повинні бути в змозі визначити, що obj.someProp не визначено, щоб ви могли подивитися на obj.prototype.someProp і вперед по ланцюжку, поки не знайдете значення. Якщо obj.someProp повернув null, не було б способу дізнатися, чи дійсно це було null або просто означало "подивіться на мій прототип". Єдиний інший спосіб це ввести кумедну магію за лаштунками, яка порушує вашу здатність метушитися з прототипами ланцюгів і робити різні інші біти чорної магії JS.
Як і у багатьох Javascript, ідея невизначеного та нульового здається спочатку хитрою і дурною, потім абсолютно блискучою (потім повертається до химерної та дурної, але з розумним поясненням).
Мова на зразок C # не буде компілюватися, якщо ви отримуєте доступ до властивості, яка не існує, а інші динамічні мови часто викидають винятки під час виконання, коли ви торкаєтесь властивості, яка не існує, тобто вам потрібно використовувати спеціальні конструкції для тестування на них. Плюс класів означає, що коли об'єкт інстанційований, ви вже знаєте його ланцюг успадкування та всі властивості, які він має - в JS я можу змінити прототип на 15 сходинок ланцюга, і ці зміни з’являться на існуючих об'єктах.
undefined
та коли користуватисяnull