7 советов по работе с undefined в JS

JavaScript

оригинал:Рисовое путешествие avlutin.com/7-tips-to-also…

Переводчик: Front-end Xiaozhi

Ставь лайк и смотри, поиск в WeChat【Переезд в мир】Обратите внимание на этого человека, который не имеет большого фабричного прошлого, но имеет восходящий и позитивный настрой. эта статьяGitHub GitHub.com/QQ449245884…Он был включен, статьи были классифицированы, и многие мои документы и учебные материалы были систематизированы.

Все говорили, что нет проекта для написания резюме, поэтому я помог вам найти проект, и это было с бонусом.【Учебник по строительству】.

Около 8 лет назад, когда оригинальный автор начал изучать JS, он столкнулся со странной ситуацией, когда обаundefinedзначение, есть также нулевое значениеnull. Какая очевидная разница между ними?Они оба вроде бы определяют null и, более того, сравниваютnull == undefinedРезультат расчетаtrue.

Большинство современных языков, таких как Ruby, Python или Java, имеют значение null (nilилиnull), что кажется разумным способом.

Для JavaScript интерпретатор возвращает значение при доступе к переменной или свойству объекта, которые не были инициализированы.undefined. Например:

let company;
company;    // => undefined
let person = { name: 'John Smith' };
person.age; // => undefined

с другой стороны,nullУказывает на отсутствующую ссылку на объект, сам JS не устанавливает для переменной или свойства объекта значениеnull.

Некоторые собственные методы, такие какString.prototype.match(), может вернутьсяnullизображать недостающие предметы. Взгляните на пример ниже:

let array = null;  
array;                // => null
let movie = { name: 'Starship Troopers',  musicBy: null };
movie.musicBy;        // => null
'abc'.match(/[0-9]/); // => null 

Из-за разрешающей природы JS разработчикам легко получить доступ к неинициализированным значениям, и я тоже допустил эту ошибку.

Часто эта опасная операция порождаетundefinedсвязанные ошибки, чтобы быстро завершить сценарий. Связанные распространенные сообщения об ошибках:

  • TypeError: 'undefined' is not a function
  • TypeError: Cannot read property '<prop-name>' of undefined
  • type errors

Разработчики JS могут понять иронию этой шутки:

function undefined() {
  // problem solved
}

Чтобы снизить риск таких ошибок, необходимо понимать генерациюundefinedСлучай. Что более важно, так это подавить его появление и предотвратить его распространение в приложении, тем самым повышая устойчивость кода.

Давайте подробно обсудимundefinedи его влияние на безопасность кода.

какого черта не определено

JS имеет 6 основных типов

  • Boolean: trueилиfalse
  • Number: 1, 6.7, 0xFF
  • String: "Gorilla and banana"
  • Symbol: Symbol("name") (starting ES2015)
  • Null: null
  • Undefined: undefined.

И отдельныйObjectТипы:{name: "Dmitri"}, ["apple", "orange"].

согласно сСпецификация ECMAScript, из 6 примитивных типов,undefinedэто особая ценность, которая имеет своюUndefinedТипы.

Значение по умолчанию, когда переменная не назначается значение,undefined.

Стандарт четко определяет, что при доступе к неинициализированным переменным, несуществующим свойствам объекта, несуществующим элементам массива и т. д. вы получитеundefinedценность . Например

let number;
number;     // => undefined

let movie = { name: 'Interstellar' };
movie.year; // => undefined

let movies = ['Interstellar', 'Alexander'];
movies[3];  // => undefined

Общий поток приведенного выше кода:

  • неинициализированная переменнаяnumber
  • несуществующее свойство объектаmovie.year
  • или не существует фильмов элементов массива3

будет определяться какundefined.

Спецификация ECMAScript определяетundefinedтип значения

Undefined typeявляется его уникальной ценностьюundefinedТип значения.

в этом смысле,typeof undefinedВозвращает «неопределенную» строку

typeof undefined === 'undefined'; // => true    

КонечноtypeofХороший способ проверить, что переменная содержитundefinedзначение

let nothing;
typeof nothing === 'undefined';   // => true  

2. Создайте неопределенные общие сценарии

2.1 Неинициализированные переменные

Объявленная переменная, которой не было присвоено значение (неинициализированная), по умолчанию имеет значениеundefined.

let myVariable;
myVariable; // => undefined    

myVariableОбъявлено, но еще не назначено, значение по умолчанию равноundefined.

Эффективный способ решить проблему неинициализированных переменных — присвоить начальные значения везде, где это возможно. Чем меньше переменных находится в неинициализированном состоянии, тем лучше. В идеале можно объявитьconst myVariable ='Initial value'Указание значения сразу после этого не всегда возможно.

Совет 1: Используйте const вместо var и пусть

На мой взгляд, одна из лучших функций ES6 — это использованиеconstа такжеletНовый способ объявления переменных.constа такжеletИмеет блочную область (в отличие от старой области действия функции)varвместо этого) присутствуют перед строкой объявленияВременная мертвая зона.

Когда переменная получает значение один раз и навсегда, рекомендуется использоватьconstобъявление, которое создает неизменяемую привязку.

constПриятной особенностью является то, что это должна быть переменнаяconst myVariable ='initial'Задайте начальное значение. Переменная не подвергается воздействию неинициализированного состояния, и доступundefinedэто невозможно.

В следующем примере проверяется функция, которая проверяет, является ли слово палиндромом:

function isPalindrome(word) {
  const length = word.length;
  const half = Math.floor(length / 2);
  for (let index = 0; index < half; index++) {
    if (word[index] !== word[length - index - 1]) {
      return false;
    }
  }
  return true;
}
isPalindrome('madam'); // => true
isPalindrome('hello'); // => false    

lengthа такжеhalfПеременной присваивается значение один раз. объявить их какconstКажется разумным, поскольку эти переменные не меняются.

Если вам нужно повторно связать переменную (т.е. несколько назначений), применитеletутверждение. По возможности сразу присваивайте ему начальное значение, например,let index = 0.

затем используйтеvarДекларация, относительно ES6, рекомендуется полностью отказаться от ее использования.

varОбъявленные упоминания переменных поднимаются вверх всей области действия функции. Может быть объявлен где-то в конце области видимости функции.varпеременная, но доступ к ней возможен до объявления: значение соответствующей переменной равноundefined.

Вместо этого используйтеletилиconstДоступ к переменной невозможен до объявленной переменной. Это происходит потому, что переменная находится вВременная мертвая зона. Это хорошо, потому что тогда меньше возможностей получить доступundefinedстоимость.

использоватьlet(вместо var) обновленный пример выше выдаетReferenceErrorОшибка, потому что переменная во временной мертвой зоне недоступна.

function bigFunction() {
  // code...
  myVariable; // => Throws 'ReferenceError: myVariable is not defined'
  // code...
  let myVariable = 'Initial value';
  // code...
  myVariable; // => 'Initial value'
}
bigFunction();

Совет 2: повышайте сплоченность

Связность описывает степень, в которой элементы модуля (пространства имен, классы, методы, блоки кода) связаны. Меру сплоченности часто называют высокой сплоченностью или низкой сплоченностью.

Предпочтение отдается высокой связности, поскольку она предполагает разработку элементов модуля таким образом, чтобы они фокусировались только на одной задаче, составляющей модуль.

  • Сосредоточенно и понятно: легче понять функцию модуля

  • Поддерживается и упрощается рефакторинг: изменения в модуле влияют на меньшее количество модулей.

  • Возможность повторного использования: сосредоточьтесь на одной задаче, что упрощает повторное использование модулей.

  • Тестируемость: модули, ориентированные на одну задачу, легче тестировать.

Высокая сплоченность и низкая связанность - это хорошо продуманные системные функции.

Сам код кода может рассматриваться как небольшой модуль, максимально возможен для достижения высокой сплоченности, необходимо использовать их как можно ближе к переменной положении блока кода.

Например, если переменная существует только для формирования области блока, не выставляйте эту переменную во внешнюю область блока, так как внешний блок не должен заботиться об этой переменной.

Классический пример ненужного увеличения времени жизни переменной — функцияforИспользование петель:

function someFunc(array) {
  var index, item, length = array.length;
  // some code...
  // some code...
  for (index = 0; index < length; index++) {
    item = array[index];
    // some code...
  }
  return 'some result';
}

index,itemа такжеlengthПеременные объявляются в начале тела функции, однако используются они только в конце, так что же в этом плохого?

Декларация сверхуforПеременные index и item в операторе не инициализированы, а значение равноundefined. Они имеют неоправданно большое время жизни во всем диапазоне функций.

Лучшим подходом является максимальное перемещение этих переменных туда, где они используются:

function someFunc(array) {
  // some code...
  // some code...
  const length = array.length;
  for (let index = 0; index < length; index++) {
    const item = array[index];
    // some 
  }
  return 'some result';
}

indexа такжеitemпеременные существуют только вforв рамках заявления,forСнаружи это не имеет никакого смысла.lengthПеременная также объявляется рядом с тем местом, где она используется.

Почему модифицированная версия лучше оригинальной? Есть несколько основных моментов:

  • переменная не раскрытаundefinedсостояние, поэтому нет доступаundefinedриски

  • Перемещение переменных как можно ближе к тому месту, где они используются, повышает читабельность кода.

  • Высокосвязный реконструированный кодовый блок легче отделить и извлечь функцию, где это необходимо

2.2 Доступ к несуществующим свойствам

При доступе к несуществующему свойству объекта JS возвращаетundefined.

Проиллюстрируем это на примере:

let favoriteMovie = {
  title: 'Blade Runner'
};
favoriteMovie.actors; // => undefined

favoriteMovieэто один атрибутtitleОбъект. Использование средств доступа к свойствамfavoriteMovie.actorsполучить доступ к несуществующему свойствуactorsбудет рассчитываться какundefined.

Доступ к несуществующему свойству сам по себе не приводит к ошибке, но возникают проблемы при попытке получить данные из значения несуществующего свойства. Распространенные ошибкиTypeError: Cannot read property <prop> of undefined.

Слегка измените предыдущий фрагмент кода, чтобы проиллюстрироватьTypeError throw:

let favoriteMovie = {
  title: 'Blade Runner'
};
favoriteMovie.actors[0];
// TypeError: Cannot read property '0' of undefined

favoriteMovieнет атрибутаactors,такfavoriteMovie.actorsзначениеundefined. Поэтому, используя выражениеfavoriteMovie.actors[0]доступundefinedПервый элемент значения выбрасываетTypeError.

JS разрешает доступ к несуществующим свойствам, и эта функция разрешения доступа может сбивать с толку: свойства могут быть установлены или не установлены, и идеальный способ обойти это — ограничить объект, чтобы он всегда определял свойства, которые он содержит.

К сожалению, мы часто не можем контролировать объекты. Эти объекты могут иметь разные наборы свойств в разных сценариях, поэтому все эти сценарии необходимо обрабатывать вручную:

Затем реализуем функциюappend(array, toAppend), его основная функция добавляет новые элементы в начало и/или конец массива.toAppendПараметр принимает объект со свойствами:

  • first: элемент вставляется в начало массива

  • last: элемент вставляется в конец массива.

Функция возвращает новый экземпляр массива без изменения исходного массива (т. е. это чистая функция).

append()Первая версия, которая выглядит проще, выглядит так:

function append(array, toAppend) {
  const arrayCopy = array.slice();
  if (toAppend.first) {
    arrayCopy.unshift(toAppend.first);
  }
  if (toAppend.last) {
    arrayCopy.push(toAppend.last);
  }
  return arrayCopy;
}
append([2, 3, 4], { first: 1, last: 5 }); // => [1, 2, 3, 4, 5]
append(['Hello'], { last: 'World' });     // => ['Hello', 'World']
append([8, 16], { first: 4 });            // => [4, 8, 16]

из-заtoAppendобъект может быть опущенfirstилиlastсвойство, поэтому оно должно быть провереноtoAppendсуществуют ли эти свойства в . Если свойство не существует, значением метода доступа к свойству являетсяundefined.

экзаменfirstилиlastЯвляется собственностьюundefined, при условииif(toappendix .first){}и яf(toappendix .last){}Подтвердить в:

Этот метод имеет недостаток,undefined,false,null,0,NaNа также''является ложным значением.

существуетappend()В текущей реализации функции не разрешено вставлять элемент виртуального значения:

append([10], { first: 0, last: false }); // => [10]

0а такжеfalseявляется фиктивным. потому чтоif(toAppend.first){}а такжеif(toAppend.last){}на самом деле сfalsyдля сравнения, чтобы элементы не вставлялись в массив, функция возвращает исходный массив[10]без какой-либо модификации.

Следующие советы объясняют, как правильно проверить наличие свойства.

Совет 3. Проверьте, существует ли свойство

JS предоставляет множество способов определить, имеет ли объект определенное свойство:

  • obj.prop!== undefined: непосредственно сundefinedСравнивать

  • typeof obj.prop!=='undefined': Проверить тип значения свойства

  • obj.hasOwnProperty('prop'): Убедитесь, что объект имеет свои собственные свойства

  • 'prop' in obj: Убедитесь, что объект имеет свои собственные свойства или унаследованные свойства.

Мое предложение состоит в том, чтобы использоватьinоператора, его синтаксис короткий и лаконичный.inНаличие оператора указывает на явное намерение проверить, имеет ли объект определенное свойство, не обращаясь к фактическому значению свойства.

obj.hasOwnProperty('prop')также хорошее решение, оно лучше, чемinОператор немного длиннее и проверяется только в собственных свойствах объекта.

с участием иundefinedСравнение оставшихся двух способов может сработать, но, на мой взгляд,obj.prop!== undefinedа такжеtypeof obj.prop!=='undefined'выглядит многословным и странным и подвергает непосредственному обращениюundefinedподозрительный путь. .

давайте использоватьinулучшения оператораappend(array, toAppend)функция:

function append(array, toAppend) {
  const arrayCopy = array.slice();
  if ('first' in toAppend) {
    arrayCopy.unshift(toAppend.first);
  }
  if ('last' in toAppend) {
    arrayCopy.push(toAppend.last);
  }
  return arrayCopy;
}
append([2, 3, 4], { first: 1, last: 5 }); // => [1, 2, 3, 4, 5]
append([10], { first: 0, last: false });  // => [0, 10, false]

'first' in toAppend(а также'last' in toAppend) когда соответствующий атрибут существуетtrue, иначеfalse.inИспользование оператора решает вставку фиктивных элементов0а такжеfalseЭта проблема. сейчас на[10]Добавление этих элементов в начало и конец[0,10,false].

Совет 4: деструктуризация доступа к свойствам объекта

При доступе к свойствам объекта иногда необходимо указать значение по умолчанию, если свойство не существует. можно использоватьinи тернарный оператор для достижения этого.

const object = { };
const prop = 'prop' in object ? object.prop : 'default';
prop; // => 'default'

Использование синтаксиса тернарного оператора становится пугающим, когда количество проверяемых свойств увеличивается. Для каждого свойства приходилось создавать новую строку кода для обработки значения по умолчанию, что добавляло уродливую стену, полную похожих тернарных операторов.

Для более элегантного подхода можно использовать деструктурирование объектов ES6.

Деструктуризация объекта позволяет извлекать значения свойств объекта непосредственно в переменные и устанавливать значения по умолчанию, когда свойство не существует, избегая прямой обработкиundefinedУдобная грамматика.

На самом деле извлечение атрибутов теперь выглядит коротким и осмысленным:

const object = {  };
const { prop = 'default' } = object;
prop; // => 'default'

Чтобы увидеть это в действии, давайте определим полезную функцию, заключающую строку в кавычки.quote(subject, config)Принимает первый аргумент в виде строки для переноса. второй параметрconfigявляется объектом со следующими свойствами:

  • char: завернутый символ, например.'(одинарные кавычки) или(двойные кавычки), по умолчанию.

  • skipIfQuoted: логическое значение для пропуска кавычек, если строка уже заключена в кавычки, по умолчаниюtrue.

Используя преимущества деструктора объекта, реализуемquote()

function quote(str, config) {
  const { char = '"', skipIfQuoted = true } = config;
  const length = str.length;
  if (skipIfQuoted
      && str[0] === char
      && str[length - 1] === char) {
    return str;
  }
  return char + str + char;
}
quote('Hello World', { char: '*' });        // => '*Hello World*'
quote('"Welcome"', { skipIfQuoted: true }); // => '"Welcome"'

const {char = '", skipifquote = true} = configРазрушение присваивания в одной строке изconfigизвлечение объектаcharа такжеskipifquoteАтрибуты. еслиconfigВ объекте есть некоторые свойства, которые недоступны, тогда назначение деструктурирования установит значения по умолчанию:charдля'"',skipifquoteдляfalse.

Эту функцию еще можно улучшить. Давайте переместим назначение деструктурирования непосредственно в раздел параметров. и дляconfigПараметр устанавливает значение по умолчанию (пустой объект{}), чтобы пропустить второй параметр, если достаточно значения по умолчанию.

function quote(str, { char = '"', skipIfQuoted = true } = {}) {
  const length = str.length;
  if (skipIfQuoted
      && str[0] === char
      && str[length - 1] === char) {
    return str;
  }
  return char + str + char;
}
quote('Hello World', { char: '*' }); // => '*Hello World*'
quote('Sunny day');                  // => '"Sunny day"'

Обратите внимание, что присваивание деструктуризации заменяет функциюconfigпараметр. Мне это нравится:quote()Одну строку сократили.={}Убедитесь, что в правой части назначения деструктурирования используется пустой объект, вообще не указывая второй параметр.

Деструктуризация объектов — это мощная функция, которая эффективно обрабатывает извлечение свойств из объектов. Мне нравится возможность указать значение по умолчанию, которое будет возвращаться, когда запрашиваемое свойство не существует. потому что это позволяет избежатьundefinedи вопросы связанные с ним.

Совет 5: Заполните объекты свойствами по умолчанию

Объекты, у которых отсутствуют некоторые свойства, можно заполнить значениями по умолчанию, если нет необходимости создавать переменные для каждого свойства наподобие присваивания деструктурирования.

ES6 Object.assign(target,source1,source2,...)Копирует значения всех перечисляемых собственных свойств из одного или нескольких исходных объектов в целевой объект, и функция возвращает целевой объект.

Например, необходимо получить доступunsafeOptionsСвойство объекта, которое не всегда содержит полный набор свойств.

Чтобы избежатьunsafeOptionsДоступ к несуществующему свойству, внесем некоторые коррективы:

  • Определяет свойство, которое содержит значения свойств по умолчанию.defaultsобъект

  • передачаObject.assign({},defaults,unsafeOptions)строить новые объектыoptions. новый объект изunsafeOptionsПолучает все свойства, но отсутствующие свойства отdefaultsприобретение объекта.

    const unsafeOptions = {
      fontSize: 18
    };
    const defaults = {
      fontSize: 16,
      color: 'black'
    };
    const options = Object.assign({}, defaults, unsafeOptions);
    options.fontSize; // => 18
    options.color;    // => 'black'

unsafeOptionsсодержит толькоfontSizeАтрибуты.defaultsСвойства определения объектаfontSizeа такжеcolorзначение по умолчанию для .

Object.assign()Возьмите первый аргумент в качестве целевого объекта{}. целевой объект изunsafeOptionsисходный объект получаетfontSizeСтоимость имущества. и людиdefaultsприобретение объектаcolorзначение атрибута, потому чтоunsafeOptionsне содержитcolorАтрибуты.

Перечисление последовательности исходного объекта очень важно: задняя обложка перед свойством исходного объекта свойство исходного объекта.

теперь безопасно доступенoptionsлюбое свойство объекта, в том числеoptions.colorв начальномunsafeOptionsнедоступен в .

Существует также простой способ использования оператора распространения в ES6:

const unsafeOptions = {
  fontSize: 18
};
const defaults = {
  fontSize: 16,
  color: 'black'
};
const options = {
  ...defaults,
  ...unsafeOptions
};
options.fontSize; // => 18
options.color;    // => 'black'

Инициализаторы объектов изdefaultsа такжеunsafeOptionsРасширенные свойства исходного объекта. Порядок, в котором указываются исходные объекты, важен, так как более поздние свойства исходных объектов переопределяют более ранние исходные объекты.

Заполнение незавершенных объектов значениями свойств по умолчанию — эффективная стратегия, позволяющая сделать ваш код безопасным и долговечным. В любом случае объект всегда содержит полный набор свойств: и не может быть сгенерированundefinedхарактеристики.

2.3 Функциональные параметры

Параметры функции неявно по умолчанию равныundefined.

Как правило, функции, определенные с определенным количеством параметров, должны вызываться с таким же количеством параметров. В этом случае параметр получает желаемое значение.

function multiply(a, b) {
  a; // => 5
  b; // => 3
  return a * b;
}
multiply(5, 3); // => 15

передачаmultiply(5,3)сделать параметрaа такжеbполучить соответствующий5а также3значение, возвращаемый результат:5 * 3 = 15.

Что происходит, когда вы опускаете аргументы при вызове?

function multiply(a, b) {
  a; // => 5
  b; // => undefined
  return a * b;
}
multiply(5); // => NaN

функцияmultiply(a, b){}по двум параметрамaа такжеbопределение. передачаmultiply(5)выполнить с одним аргументом: результат один аргумент5,ноbпараметрundefined.

Совет 6. Используйте значения параметров по умолчанию

Иногда функции не требуется полный набор аргументов для вызова, и вы можете просто установить значения по умолчанию для аргументов, которые не имеют значений.

Возвращаясь к предыдущему примеру, давайте сделаем улучшение, еслиbЕсли параметр не определен, ему присваивается значение по умолчанию.2:

function multiply(a, b) {
  if (b === undefined) {
    b = 2;
  }
  a; // => 5
  b; // => 2
  return a * b;
}
multiply(5); // => 10

Хотя предоставленный метод присвоения значения по умолчанию работает, не рекомендуется напрямую взаимодействовать сundefinedзначение для сравнения. Это многословно и похоже на взлом.

Здесь можно использовать значения по умолчанию ES6:

function multiply(a, b = 2) {
  a; // => 5
  b; // => 2
  return a * b;
}
multiply(5);            // => 10
multiply(5, undefined); // => 10  

2.4 Возвращаемое значение функции

косвенно, нетreturnзаявление, функция JS возвращаетundefined.

В JS нетreturnФункция оператора возвращает неявноundefined:

function square(x) {
  const res = x * x;
}
square(2); // => undefined  

square()Функция не возвращает результат вычисления, результат при вызове функцииundefined.

когдаreturnВозвращает по умолчанию, если после оператора нет выраженияundefined.

function square(x) {
  const res = x * x;
  return;
}
square(2); // => undefined

return;Оператор выполняется, но не возвращает никакого выражения, и результат вызова такжеundefined.

function square(x) {
  const res = x * x;
  return res;
}
square(2); // => 4

Совет 7: не доверяйте автоматической вставке точки с запятой

Перед следующим списком операторов в JS должна стоять точка с запятой(;)конец:

  • пустой оператор

  • let,const,var,import,exportутверждение

  • выразительное заявление

  • debuggerутверждение

  • continueутверждение,breakутверждение

  • throwутверждение

  • returnутверждение

Если вы используете одно из приведенных выше объявлений, постарайтесь указать в концеточка с запятой:

function getNum() {
  let num = 1; 
  return num;
}
getNum(); // => 1

letзаявление иreturnВ конце заявления обязательно написатьточка с запятой.

Что происходит, когда вы не хотите писать эти точки с запятой? Например, мы хотим уменьшить размер исходного файла.

В этом случае ECMAScript предоставляетМеханизм автоматической вставки точки с запятой (ASI), вставки для васотсутствует точка с запятой.

С помощью ASI это можно сделать из предыдущего примераудалить точку с запятой:
function getNum() { // Notice that semicolons are missing let num = 1 return num } getNum() // => 1

Приведенный выше код является действительным кодом JS, отсутствующийточка с запятойASI автоматически вставит его для нас.

На первый взгляд выглядит красиво. Механизм ASI позволяет писать меньше ненужных точек с запятой, что может сделать код JS меньше и его легче читать.

ASI создает небольшую, но раздражающую ловушку. когда новая строка находится вreturnа такжеreturn \n expressionASI автоматически вставляет точку с запятой перед новой строкой (return; \n expression).

внутри функцииreturn;? то есть функция возвращаетundefined. Если вы не понимаете механизм ASI в деталях, неожиданно возвращаетсяundefinedМогут возникнуть неожиданные проблемы.

ПриходитьgetPrimeNumbers()Значение, возвращаемое вызовом:

function getPrimeNumbers() {
  return 
    [ 2, 3, 5, 7, 11, 13, 17 ]
}
getPrimeNumbers() // => undefined

существуетreturnМежду оператором и массивом есть новая строка, JS вreturnАвтоматически после точки с запятой, интерпретируемый код следующим образом:

function getPrimeNumbers() {
  return; 
  [ 2, 3, 5, 7, 11, 13, 17 ];
}
getPrimeNumbers(); // => undefined

return;сделать функциюgetPrimeNumbers()вернутьundefinedвместо ожидаемого массива.

Этот вопрос снимаетсяreturnи новые строки между литералами массива для разрешения:

function getPrimeNumbers() {
  return [ 
    2, 3, 5, 7, 11, 13, 17 
  ];
}
getPrimeNumbers(); // => [2, 3, 5, 7, 11, 13, 17]

Мой совет - изучитьТочный способ автоматической вставки точки с запятой, чтобы избежать этого.

Конечно, никогдаreturnМежду выражением и возвращаемым выражением помещается новая строка.

2.5 Пустой оператор

void <expression>Вычисляемое выражение возвращается независимо от результата вычисленияundefined.

void 1;                    // => undefined
void (false);              // => undefined
void {name: 'John Smith'}; // => undefined
void Math.min(1, 3);       // => undefined

voidОдним из вариантов использования операторов является ограничение вычисления выражений доundefined, который зависит от некоторых побочных эффектов оценки.

3. Неопределенный массив

При доступе к элементу массива с индексом за пределами границ вы получаетеundefined.

const colors = ['blue', 'white', 'red'];
colors[5];  // => undefined
colors[-1]; // => undefined

colorsМассив состоит из 3 элементов, поэтому допустимый индекс0,1а также2.

из-за индекса5а также-1Элементов массива нет, поэтому доступcolors[5]а такжеcolors[-1]значениеundefined.

В JS вы можете столкнуться с так называемыми разреженными массивами. Эти массивы разрываются, то есть по определенным индексам ни один элемент не определен.

При доступе к промежутку (также известному как пустой слот) в разреженном массиве вы также получаетеundefined.

Следующий пример создает разреженные массивы и пытается получить доступ к их пустым слотам.

const sparse1 = new Array(3);
sparse1;       // => [<empty slot>, <empty slot>, <empty slot>]
sparse1[0];    // => undefined
sparse1[1];    // => undefined
const sparse2 = ['white',  ,'blue']
sparse2;       // => ['white', <empty slot>, 'blue']
sparse2[1];    // => undefined

При использовании массивов, во избежание полученияundefined, обязательно используйте допустимые индексы массива и избегайте создания разреженных массивов.

4. Разница между undefined и null

Возникает закономерный вопрос:undefinedа такжеnullВ чем основная разница между двумя этими специальными значениями, представляющими пустое состояние.

Основное отличие в том, чтоundefinedпредставляет значение переменной, которая еще не была инициализирована,nullУказывает, что объект не существует намеренно.

Давайте рассмотрим различия между ними на некоторых примерах.

число определено, но ему не присвоено значение.

let number;
number; // => undefined

numberПеременная не определена, что явно указывает на неинициализированную переменную.

Та же концепция неинициализированного также возникает при доступе к несуществующему свойству объекта.

const obj = { firstName: 'Dmitri' };
obj.lastName; // => undefined

потому чтоobjне существует вlastNameсвойство, поэтому JS правильно будетobj.lastNameРассчитано какundefined.

В других случаях вы знаете, что переменная ожидает объект или функцию, которая возвращает объект. Но по какой-то причине вы не можете создать экземпляр этого объекта. при этих обстоятельствах,nullявляется значимым индикатором отсутствующих объектов.

Например,clone()это функция, которая клонирует обычный объект JS, функция вернет объект

function clone(obj) {
  if (typeof obj === 'object' && obj !== null) {
    return Object.assign({}, obj);
  }
  return null;
}
clone({name: 'John'}); // => {name: 'John'}
clone(15);             // => null
clone(null);           // => null

Однако можно вызывать с аргументами, не являющимися объектами.clone(): 15илиnull(или обычно примитивное значение,nullилиundefined). В этом случае функция не может создать клон, поэтому возвращаетnull- индикатор пропавшего предмета.

typeofоператор различает два значения

typeof undefined; // => 'undefined'
typeof null;      // => 'object'

оператор строгого равенства===может правильно различатьundefinedа такжеnull:

let nothing = undefined;
let missingObject = null;
nothing === missingObject; // => false

Суммировать

undefinedСуществование JS является результатом разрешительного характера JS, который позволяет использовать:

  • неинициализированная переменная
  • Несуществующее свойство или метод объекта
  • доступ к элементу массива по индексу за пределами границ
  • результат вызова функции, которая не возвращает результата

В большинстве случаев непосредственно сundefinedСравнение — плохая практика. Эффективная стратегия заключается в уменьшении количестваundefinedВозникновение ключевых слов:

  • Уменьшите использование неинициализированных переменных

  • Сделайте время жизни переменной коротким и близким к тому, где она используется.

  • Присваивайте начальные значения переменным, когда это возможно

  • Более формальный const и пусть

  • Используйте значение по умолчанию, чтобы указать несущественный параметр функции

  • Проверить существование свойства или заполнить небезопасный объект свойством по умолчанию

  • Избегайте разреженных массивов

Ошибки, которые могут существовать после развертывания кода, не могут быть известны в режиме реального времени.Чтобы решить эти ошибки впоследствии, много времени тратится на отладку журнала.Кстати, я рекомендую всем полезный инструмент мониторинга ошибок.Fundebug.

общаться с

Статья постоянно обновляется каждую неделю. Вы можете выполнить поиск «Big Move to the World» в WeChat, чтобы прочитать и обновить ее как можно скорее (на одну или две статьи раньше, чем в блоге). Эта статья находится на GitHub.GitHub.com/QQ449245884…Он был включен, и многие мои документы были разобраны. Добро пожаловать в Звезду и совершенство. Вы можете обратиться в тестовый центр для ознакомления во время собеседования. Кроме того, обратите внимание на паблик-аккаунт и ответьте в фоновом режиме.Благосостояние, вы можете увидеть преимущества, вы знаете.