typeof! == "undefined" vs.! = null


491

Я часто бачу код JavaScript, який перевіряє невизначені параметри і т.д. таким чином:

if (typeof input !== "undefined") {
    // do stuff
}

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

Моє запитання:
Як цей код краще, ніж цей підхід:

if (null != input) {
    // do stuff
}

Наскільки я знаю, ви не можете переосмислити null, тож несподівано це не вийде. І через тиск примусу !=оператора, це перевіряє як undefinedі null..., що часто саме те, що ви хочете (наприклад, для додаткових параметрів функції).

Але ця форма не здається широко розповсюдженою, і вона навіть змушує JSLint кричати на вас за те, що ви використовуєте злий !=оператор.

Чому це вважається поганим стилем?


13
@ Марсель, різниці немає, але це є дві причини. Одне, це те, що для деяких це зрозуміліше читати. А друга причина - це те, що вона запобігає випадковому перезапису змінної. Ви коли-небудь робили це: if (foo = "value"), коли збираєтеся зробити порівняння. Якщо ви ввійдете в звичку повертати змінну в операторі присвоєння / порівняння, у вас не виникне такої проблеми.
Layke

29
Для деяких (включаючи мене) це насправді важче читати. Крім того, більшість IDE попереджають вас про випадкове призначення. Але я все одно використовую цю форму, якщо порівнянна змінна дуже довга. YMMV.
johndodo

15
@MarcelKorpel Це називається "умова Yoda": umumble.com/blogs/Programming/321
kol

55
Це важче читати. Один не каже "Не порожня пляшка".
Ноель Абрахамс

11
if (null != input)є лише "Yoda Speak" для англійського мовця (з одного я .... uuammmmm), тож якщо вони прирівнюють до одного і того ж, це справді просто семантика. ІМХО.
webLacky3rdClass

Відповіді:


709

typeof є безпечнішим, оскільки дозволяє ідентифікатору ніколи не декларуватися раніше:

if(typeof neverDeclared === "undefined") // no errors

if(neverDeclared === null) // throws ReferenceError: neverDeclared is not defined

3
if ((typeof neverDeclared! == "undefined") && (neverDeclared! == null)) {return true; } else {return false; }
Ентоні Дісанті

88
Використовуйте === при порівнянні з null / undefined.
MyGGaN

47
@MyGGaN лише в тому випадку, якщо ви хочете розмежувати їх. У багатьох випадках ==може бути кращим, оскільки він тестує як нульові, так і невизначені.
seanmonstar

10
Я не можу знайти різниці між typeof somevar == 'undefined' і typeof somevar === 'undefined', тому що typeof завжди повертає рядок. Для null він поверне 'object'. Або могло бути, що я помиляюся?
TomTom

2
Я вважаю, що коментар @ TomTom є сутністю проблеми - я не можу зрозуміти, чому можна використовувати оператори !==або ===оператори при порівнянні значення, тип якого, як відомо, є рядком.
Nicolas Rinaudo

49

Якщо змінна оголошена (або за допомогою varключового слова, як аргументу функції, або як глобальної змінної), я вважаю, що найкращий спосіб це зробити:

if (my_variable === undefined)

jQuery це робить, тому для мене це досить добре :-)

В іншому випадку вам доведеться використовувати, typeofщоб уникнути ReferenceError.

Якщо ви очікуєте, що невизначене значення буде переосмислено, ви можете перетворити свій код таким чином:

(function(undefined){
    // undefined is now what it's supposed to be
})();

Або отримати його через voidоператора:

const undefined = void 0;
// also safe

1
Якщо undefined вже визначено, то чи не передасте ви його анонімній функції через параметр, визначений undefined, нічого не виконуючи?
Ентоні Дісанті

20
@Anthony DiSanti: Ні, undefinedце ім'я, яке задається параметру функції, а не його значення. Функція нічого не передається, тобто значення першого параметра не визначене.
Джої Адамс

3
Ах, моя помилка, дякую за наступні дії. Я зняв свій голос, вибачте за це.
Ентоні Дісанті

2
Навіщо писати виняток, щоб обробляти невизначене оголошення, заявлене іншим розробником, коли ви можете просто зробити це правильно для початку? jQuery обертає початкову анонімну функцію, коли ви показуєте у своїй функції, щоб переконатися, що невизначений не був визначений та зменшити зменшений розмір. Простіше кажучи, якщо це може дати несподівані результати, щоб зробити це таким чином, навіщо ризикувати для ледачого програмування, щоб уникнути набору тексту (typeof змінна === 'undefined'). Що робити, якщо ми хотіли (typeof змінної === 'об’єкт'), чи слід надати змінну за замовчуванням, яка також є об'єктом, щоб ми могли це зробити (змінний === об'єкт)?
fyrye

28

хороший спосіб:

if(typeof neverDeclared == "undefined") //no errors

Але найкраще виглядати за допомогою:

if(typeof neverDeclared === typeof undefined) //also no errors and no strings

6
var undefined = function () {}; if (typeof neverDeclared === typeof undefined); neverDecalred! = 'функція'; jsfiddle.net/hbPZ5 return typeof var; повертає рядок. Немає помилок чи рядків, але не завжди дасть очікувані результати. Зазначені розробники не повинні оголошувати невизначені, але є деякі рамки та бібліотеки, які це роблять.
fyrye

1
Я в основному використовую, if (typeof neverDeclared === typeof undefined) { але Линт видає помилку. "Очікували рядок і замість цього побачив" typeof "." Як би ви обійшли цю помилку? Чи варто ми підкорятися вимогам Лінта і використовувати замість цього «добрий шлях»?
Айеліс

2
@fyrye Чи знаєте ви будь-які бібліотеки / рамки JavaScript, які насправді мутують невизначені? Я знаю, що це можливо; але я хотів би знайти дикий приклад: "Ось де ти можеш зіткнутися з цим гидким Гну!"
bigtunacan

4
typeof neverDeclared === typeof void 0;-D
Олексій Ярошевич

1
Це схильне до помилок, тому що насправді ви просто покладаєтесь на певну змінну ("невизначена"), яка не визначається. Що може бути помилковим, як показали інші пости. Ви завжди можете це зробити, if(typeof neverDeclared === typeof undefined_variable_with_a_name_assumed_to_be_never_defined) {але це досить довго.
П’єр-Олів'є Варес

12

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

(function($, Backbone, _, undefined) {
    //undefined is undefined here.
})(jQuery, Backbone, _);

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

if(window.neverDefined === undefined) {
    //Code works
}

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

Крім того, чому ваші змінні не визначені? Я бачив багато коду, де вони перевіряють наявність змінних і виконують якусь дію на основі цього. Не раз я бачив, де цей підхід був правильним.


1
Перевірка введення та перевірка залежності є вагомими причинами для використання цього. Якщо у мене є файли Javascript, які залежать від інших файлів із завантаженими або init об'єктами, які були оголошені, то корисно перевірити об'єкти чи властивості, якими файл залежить від невизначеного, і викинути приємне виняток, а не дозволяти вашому сценарію десь непередбачуваним.
AmericanUmlaut

Здається, що вам може знадобитися щось у рядках AMD (Requ.js)
Peeter

1
Або я просто хотів би зробити дуже просте порівняння, а не включати іншу бібліотеку у свій проект :)
AmericanUmlaut

Надто пізно для редагування :(. Хотів додати - Requ.js також не є правильним рішенням для перевірки вводу (об'єкти init, про які я згадував у своєму первинному коментарі). Якщо у вас є об'єкт, який, як ви очікуєте, буде заповнений певним значення перед завантаженням скрипту, тоді корисно викинути виняток, якщо вони не визначені.
AmericanUmlaut

1
Ні, тому що typeof повертає рядок. Отже, typeof undefined повертається "undefined". window.input! == undefined (якщо ваша змінна є у глобальній області)
Peeter

5

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

function is_undefined(value) {
   var undefined_check; // instantiate a new variable which gets initialized to the real undefined value
   return value === undefined_check;
}

Це працює, тому що коли хтось пише, undefined = "foo"він дозволяє лише посилання на ім'я undefined на нове значення, але він не змінює фактичне значення undefined.


1
Однак зараз ви запровадили функціональний виклик, який шкодить продуктивності.
Тім Даун

Я не думаю, що цей виклик функції знищить продуктивність, набагато ймовірніше, що DOM буде вузьким місцем. Але в будь-якому випадку, якщо у вас є звичайна велика анонімна функція, яка містить будь-яку бібліотеку, ви також можете визначити undefined_checkїї вгорі, а потім просто використовувати її скрізь у своєму коді.
Іво Ветцель,

1
Погодився, і я не кажу, що це погана ідея. Варто лише зазначити, що виклик цієї функції буде виконуватись повільніше, ніж робити typeofперевірку.
Тім Даун

Я думаю, що ця функція досить проста, щоб вона була вбудована, тому на продуктивність не впливало.
хуйз

4
@TimDown: спочатку записати код, який можна прочитати. друге пишіть код, це є ремонтом, а потім, якщо це справді повільно. то подумайте про продуктивність.
andreas

4

Ви також можете скористатися оператором void для отримання невизначеного значення:

if (input !== void 0) {
    // do stuff    
}

(І так, як зазначено в іншій відповіді, це призведе до помилки, якщо змінна не була оголошена, але цей випадок часто може бути виключений або за допомогою перевірки коду, або за допомогою рефакторингу коду, наприклад, window.input !== void 0для тестування глобальних змінних або додавання var input.)


1

Я фактично натрапив, якщо (typeof input !== 'undefined')в цьому сценарії, де він використовується для надання параметрів функції за замовчуванням:

function greet(name, greeting) {
  name = (typeof name !== 'undefined') ?  name : 'Student';
  greeting = (typeof greeting !== 'undefined') ?  greeting : 'Welcome';

  return `${greeting} ${name}!`;
}

greet(); // Welcome Student!
greet('James'); // Welcome James!
greet('Richard', 'Howdy'); // Howdy Richard!

ES6 пропонує нові способи введення параметрів функції за замовчуванням таким чином:

function greet(name = 'Student', greeting = 'Welcome') {
  return `${greeting} ${name}!`;
}

greet(); // Welcome Student!
greet('James'); // Welcome James!
greet('Richard', 'Howdy'); // Howdy Richard!

Це менш багатослівно і чіткіше, ніж перший варіант.


1

function greet(name, greeting) {
  name = (typeof name !== 'undefined') ?  name : 'Student';
  greeting = (typeof greeting !== 'undefined') ?  greeting : 'Welcome';

  console.log(greeting,name);
}

greet(); // Welcome Student!
greet('James'); // Welcome James!
greet('Richard', 'Howdy'); // Howdy Richard!

//ES6 provides new ways of introducing default function parameters this way:

function greet2(name = 'Student', greeting = 'Welcome') {
//  return '${greeting} ${name}!';
console.log(greeting,name);
}

greet2(); // Welcome Student!
greet2('James'); // Welcome James!
greet2('Richard', 'Howdy'); // Howdy Richard!


0

(function(){

  var a= b = 3;
  var ed = 103;
  
})();



//console.log(ed); //ed is not defined

console.log("a defined? " + (typeof a !== 'undefined')); //no define
console.log("b defined? " + (typeof b !== 'undefined')); //yes define
console.log(typeof(b)); //number
console.log(typeof(4+7));   //number
console.log(b); //3
console.log(typeof("4"+"7")); //string
var e= "ggg";
console.log(typeof(e)); //string
 var ty=typeof(b);
console.log(ty); //number
console.log(typeof false); //boolean
console.log(typeof 1); //number
console.log(typeof 0); //number
console.log(typeof true); //boolean


console.log(typeof Math.tan);  //function
console.log(typeof function(){}); //function 

if(typeof neverDeclared == "undefined") //no errors
if(typeof neverDeclared === "undefined") //no errors

//if(neverDeclared == null) //showing error 


console.log(typeof {a:1}); //object
console.log(typeof null); //object
console.log(typeof JSON); //object
console.log(typeof Math); //object
console.log(typeof /a-z/); //object
console.log(typeof new Date()); //object

console.log(typeof afbc); //undefined
//console.log(typeof new);//error

document.write("<br> * oprator as math ");
var r=14*"4";
document.write(r);

document.write("<br> + oprator as string ");
var r=14+"44";
document.write(r);

document.write("<br> Minus Operator work as mathematic ");
var r=64-"44";
document.write(r);


document.write("<br>");
console.log(typeof(4*"7")); //returns number
console.log(typeof(4+"7")); //returns string




 
Interview Question in JavaScript


Чи можете ви надати пояснення?
jhpratt GOFUNDME RELICENSING

Існує шість можливих значень, які typeof повертає: об'єкт, булева, функція, число, рядок та невизначене. Оператор typeof використовується для отримання типу даних (повертає рядок) свого операнду. Операнд може бути як буквальним, так і структурою даних, таким як змінна, функція або об'єкт. Оператор повертає тип даних. Синтаксис typeof операнд або typeof (операнд)
Avinash Maurya

0

var bar = null;
console.log(typeof bar === "object"); //true yes 
//because null a datatype of object

var barf = "dff";
console.log(typeof barf.constructor);//function


console.log(Array.isArray(bar));//falsss


console.log((bar !== null) && (bar.constructor === Object)); //false

console.log((bar !== null) && (typeof bar === "object"));  // logs false
//because bar!==null, bar is a object


console.log((bar !== null) && ((typeof bar === "object") || (typeof bar === "function"))); //false

console.log(typeof bar === typeof object); //false
console.log(typeof bar2 === typeof undefined); //true
console.log(typeof bar3 === typeof undefinedff); //true
console.log(typeof bar2 == typeof undefined); //true

console.log((bar !== null) && (typeof bar === "object") && (toString.call(bar) !== "[object Array]")); //false


-7
if (input == undefined) { ... }

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

else if (input) { ... }

робить це.

Якщо програма переосмислюється, undefinedвсе одно це дійсно розум.

Єдиною причиною, про яку я можу подумати, є сумісність з IE4, це не зрозуміло undefinedключове слово (яке, на жаль, не є ключовим словом), але, звичайно, значення можуть бути undefined , тому вам довелося мати це:

var undefined;

і порівняння вище буде добре працювати.

У вашому другому прикладі вам, мабуть, потрібні подвійні круглі дужки, щоб зробити обличчя щасливим?


Ви input == undefinedповернетеся trueна nullвхід.
мгol
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.