Наскільки насправді небезпечно в JavaScript, вважати, що undefined не перезаписано?


86

Кожного разу, коли хтось згадує тестування проти undefined, зазначається, що undefinedце не ключове слово, тому для нього можна встановити значення"hello" , тому замість цього слід використовувати typeof x == "undefined" . Це здається мені смішним. Ніхто ніколи цього не зробив би, і якби вони це зробили, це було б достатньою підставою ніколи не використовувати будь-який написаний ними код ... так?

Я знайшов один приклад того , хто випадково встановлений undefinedв null, і це було дано в якості причини , щоб уникнути за умови , що undefinedНЕ буде переписана. Але якби вони це зробили, помилка не виявилася б, і я не бачу, як це краще.

У C ++ всі добре знають, що це законно казати #define true false, але ніхто ніколи не радить вам уникати trueі використовувати 0 == 0замість цього. Ви просто припускаєте, що ніхто ніколи не був би настільки великим придурком, щоб це зробити, і якщо вони це роблять, ніколи більше не довіряйте своєму коду.

Це коли-небудь насправді вкусило когось, кого призначив хтось undefined(навмисно), і це зламало ваш код, чи це скоріше гіпотетична загроза? Я готовий ризикувати, щоб зробити свій код трохи читабельнішим. Це насправді погана ідея?

Повторюючи, я не запитую, як захиститись від переназначення невизначеного. Я вже бачив ці трюки, написані 100 разів. Я запитую, наскільки небезпечно не використовувати ці фокуси.


7
Я був би радий, але я не відчуваю, що будь-яка з трьох відповідей дає хорошу роботу, відповідаючи на питання. Я намагався дати зрозуміти, що не прошу переглядати відповіді, на які я посилався, але це все одно я отримав. Якщо вважається, що Gauche не приймає відповіді, навіть якщо це не те, про що я просив, дайте мені знати, і я продовжу приймати таку!
Cosmologicon

1
Мені здається, тут викладені всі факти. Отже, те, що ви говорите, - це те, що ви хочете замість цього отримати суб’єктивну відповідь чи думку, що призводить лише до розбіжностей. Саме тому фраза "найкраща практика" заборонена в назвах запитань. Ви єдина людина, яка може знати, наскільки це небезпечно у вашому сценарії. І якщо ви пишете популярну бібліотеку, де не контролюєте всі "змінні", обертка функції (undefined) {}, мабуть, є чудовою відповіддю. Чому б не використати його і не прийняти цю відповідь?
shannon

4
Якщо когось турбує, хтось переосмислює undefined, вам слід більше турбуватися про те, що хтось переосмислить XMLHttpRequest, або alert. Усі функції, якими ми користуємось, windowмогли бути перевизначені. І якщо ви просто турбуєтесь про те, що колега робить це випадково, чому довіряти їм цього не робити window.addEventListener = "coolbeans"? Відповідь - не турбуватися ні про що. Якщо хтось зловмисно вводить JS на вашу сторінку, ви все одно зробите шланг. Попрацюйте над тим, щоб запобігти цьому .
Кріс Міддлтон

Відповіді:


56

Ні, ніколи не мав. Це здебільшого тому, що я розробляю сучасні браузери, які в основному відповідають ECMAScript 5. Стандарт ES5 диктує, що undefinedзараз доступний лише для читання. Якщо ви використовуєте строгий режим (вам слід), помилка видасть помилку, якщо ви випадково спробуєте її змінити.

undefined = 5;
alert(undefined); // still undefined
'use strict';
undefined = 5; // throws TypeError

Що ви не повинні робити, це створювати власну сферу дії, що змінюється undefined:

(function (undefined) {
    // don't do this, because now `undefined` can be changed
    undefined = 5;
})();

Постійна - це добре. Все ще непотрібне, але прекрасне.

(function () {
    const undefined = void 0;
})();

Ваше перше твердження гарантує лише те, що ви випадково не перезапишете невизначене під час розробки, воно все одно створює однакову загрозу під час роботи з іншим кодом на клієнтських комп'ютерах.
bennedich

1
@bennedich: Я знаю, я говорив, що ніколи не стикався з цією проблемою, але ось що ти повинен робити .
Ry-

1
@bennedich Невже у вас однакові шанси випадково перезаписати будь-яку іншу змінну?
Ates Goral

40

Жоден правильний код не зробить такого. Але ви ніколи не можете дізнатись, що зробив якийсь розумний розробник чи плагін / бібліотека / сценарій, яким ви користуєтесь. З іншого боку, це вкрай малоймовірно, і сучасні браузери взагалі не дозволяють перезаписувати undefined, тому, якщо ви використовуєте такий браузер для розробки, ви швидко помітите, якщо будь-який код намагається його перезаписати.


І хоча ви не просили про це - багато людей, мабуть, знайдуть це питання, шукаючи найбільш поширену undefinedпроблему "як захиститися від перевизначення ", тому я все одно відповім на це:

Існує дуже хороший спосіб отримати справді невизначене, undefined незалежно від того, скільки років браузеру:

(function(undefined) {
    // your code where undefined is undefined
})();

Це працює, оскільки аргумент, який не вказаний, є завжди undefined. Ви також можете зробити це за допомогою функції, яка приймає деякі реальні аргументи, наприклад, наприклад, коли ви використовуєте jQuery. Зазвичай є гарною ідеєю забезпечити нормальне середовище таким чином:

(function($, window, undefined) {
    // your code where undefined is undefined
})(jQuery, this);

Тоді ви можете бути впевнені, що всередині цієї анонімної функції виконуються наступні речі:

  • $ === jQuery
  • window === [the global object]
  • undefined === [undefined].

Однак, зверніть увагу , що іноді typeof x === 'undefined'насправді необхідно: Якщо змінна xніколи не була встановлена на значення (всупереч бути набір до undefined), читання xпо-іншому , наприклад , як if(x === undefined)буде згенеровано повідомлення про помилку. Однак це не стосується властивостей об'єкта, тому, якщо ви знаєте, що yце завжди об'єкт, if(y.x === undefined)це абсолютно безпечно.


2
Ваше твердження про те, що xне встановлено значення, не зовсім відповідає дійсності (див. Jsfiddle.net/MgADz ); це швидше, якщо це насправді не визначено (див. jsfiddle.net/MgADz/1 ).
Ry-

7
Знову ж таки, якщо хтось випадково скаже, undefined = someVariableщо це помилка, і ви хочете , щоб речі зламалися. Принаймні я це роблю.
Cosmologicon

2
Я працював із кодовою базою, у якій був мініфікований застарілий сценарій, який переписав невизначений, у нас не було часу чи бюджету, щоб переписати сценарій. гарна звичка.
Damen TheSifter

2
Мене цікавить, чому у всіх прикладах використовується "undefined" як додатковий аргумент у функції? Але може бути ситуація, якщо хтось помилково передасть один додатковий параметр (визначений), і вся логіка буде невдалою. Чому б не використати щось на зразок функції () {var _undef; if (someVal == _undef) {щось зробити}};
Oleksandr_DJ

4
@Oleksandr_DJ Саме так. Складіть значення, яке ви знаєте , undefinedі призначте це undefinedза обсягом. Не залишайте undefinedвідкритим для перезапису, якщо ви передаєте аргументи "занадто багато". Це спричиняє помилки і за своєю суттю не є оборонним зразком, особливо коли, як зазначає Лусеро , є дуже легкі альтернативи, щоб отримати тверді undefinedзначення.
jorffin

19

Є просте рішення: порівняти, void 0яке завжди не визначено.

Зауважте, що слід уникати, ==оскільки це може примусити значення. Замість цього використовуйте ===(та !==).

Тим не менш, невизначена змінна може бути встановлена ​​помилково, якщо хтось пише =замість того, ==щоб порівнювати щось проти undefined.


ІМО, це найкраща відповідь.
abhisekp

1
Зверніть увагу, що foo === void 0читання може відбуватися не так гладко, як foo === undefinedте, що незмінний undefinedповністю підтримується сучасними браузерами (IE 9+), як ви можете бачити в цій таблиці сумісності.
Даніель АР Вернер

3

Тільки ви знаєте, яким кодом ви користуєтесь, а отже, наскільки він небезпечний. На це запитання не можна відповісти так, як ви пояснили, що хочете, щоб на нього відповіли.

1) Створіть групову політику, забороніть перевизначення невизначеного, зарезервувавши його для більш популярного використання. Скануйте свій існуючий код на невизначене ліве призначення.

2) Якщо ви не контролюєте всі сценарії, якщо ваш код використовується поза ситуаціями, якими керуєте ви або ваші політики, то, очевидно, ваша відповідь інша. Відскануйте код, який використовує ваші сценарії. Чорт, скануйте в Інтернеті статистику невизначеного лівого призначення, якщо хочете, але я сумніваюся, що це зроблено для вас, тому що тут простіше просто знайти відповідь №1 або №3.

3) І якщо ця відповідь недостатньо хороша, можливо, тому, що, знову ж таки, вам потрібна інша відповідь. Можливо, ви пишете популярну бібліотеку, яка буде використовуватися в корпоративних брандмауерах, і у вас немає доступу до телефонного коду. Тоді скористайтеся однією з інших чудових відповідей тут. Зверніть увагу на популярну бібліотеку jQuery, яка практикує інкапсуляцію звуку, і починається:

(function( window, undefined ) {

Тільки ви можете відповісти на своє запитання конкретно, як ви шукаєте. Що ще сказати?

редагувати: ps, якщо ви дійсно хочете мою думку, я скажу вам, що це зовсім не небезпечно. Все, що могло б спричинити дефекти (наприклад, віднесення до невизначеного, що, очевидно, є добре задокументованою ризикованою поведінкою), саме по собі є дефектом. Ризик - це дефект. Але це лише в моїх сценаріях, коли я можу дозволити собі дотримуватися такої перспективи. Як я б вам рекомендував, я відповів на запитання для моїх випадків використання.


3

Безпечно тестувати проти невизначеного. Як ви вже згадували. Якщо ви потрапили до якогось коду, який його замінює (що вкрай неможливо), просто більше не використовуйте його.

Можливо, якщо ви створюєте бібліотеку для загального користування, ви можете використовувати деякі з методів, щоб уникнути зміни користувачем. Але навіть у цьому випадку це їх проблема, а не ваша бібліотека.


2

Ви можете використовувати undefinedсвій код під час кодування для браузерів, що підтримують ECMAScript 5.1, оскільки він незмінний відповідно до специфікації мови .

Також перегляньте цю таблицю сумісності або цей приклад ECMAScript 5, щоб побачити, що всі сучасні браузери (IE 9+) впровадили незмінніundefined .


1

Це зовсім не небезпечно. Його можна перезаписати лише під час роботи на двигуні ES3, і це, швидше за все, більше не використовуватиметься.


0

Перш за все, якщо ваш код зламається, це, мабуть, не тому, що якийсь інший розробник там "намагається бути придурком", як ви сказали.

Це правда, що undefinedце не ключове слово. Але це глобальний рівень примітивно. Його планували використовувати таким чином (див. "Undefined" на developer.mozilla.org ):

var x;
if (x === undefined) {
    // these statements execute
}
else {
    // these statements do not execute
}

Загальною альтернативою цьому (також від MDN ) і, на мій погляд, кращим способом є:

// x has not been declared before
if (typeof x === 'undefined') { // evaluates to true without errors
    // these statements execute
}

if(x === undefined){ // throws a ReferenceError

}

Що має пару переваг, очевидним (з коментарів) є те, що воно не викликає винятку, коли х не оголошено. Варто також відзначити , що MDN також вказує на те , що важливо використовувати ===більш ==в першому випадку , так як :

var x=null;
if (x === undefined) {
    // this is probably what you meant to do
    // these lines will not execute in this case
}
else if (x == undefined) {
    // these statements will execute even though x *is* defined (as null)
}
else {
    // these statements do not execute
}

Це ще одна часто упускається з уваги причина, чому, мабуть, краще просто використовувати другу альтернативу у всіх випадках.

Висновок: Не неправильно кодувати його першим способом, і, звичайно, не небезпечно. Аргумент, який ви бачили, що використовуєте як приклад проти нього (що його можна перезаписати), не є найсильнішим аргументом для кодування альтернативи за допомогою typeof. Але використання typeofсильніше з однієї причини: воно не створює винятку, коли ваш var не оголошений. Можна також стверджувати, що використання ==замість ===є типовою помилкою, і в цьому випадку воно робить не те, що ви очікували. То чому б не використовувати typeof?


1
"Що має пару переваг, очевидним є те, що воно не викликає винятку, коли x не оголошено." Дозвольте мені це зрозуміти. Ви вважаєте перевагою мовчки ігнорувати виняток, який трапляється, коли використовується незадекларована змінна? Це здається дуже схильним до помилок. Чи можете ви пояснити, чому ви вважаєте, що це не страшний недолік?
Cosmologicon
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.