Как обрабатывать значения «null» и «undefined» при деструктурировании аргументов функции - PullRequest
1 голос
/ 11 апреля 2019
function createElement (type, { attrs = {}, children = [] }) {
 if (Object.prototype.toString.call(arguments[1]) !== '[object Object]') { 
   throw Error('The options argument must be an object'); 
 }

 return {
  type,
  attrs,
  children
 }
}

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

Когда нужно убедиться, что второй аргумент является объектом, я знаю, что могу сделать эту проверку: Object.prototype.toString.call(arguments[1] !== 'object Object').

Но если в качестве аргументов передаются null или undefined, возникает эта ошибка: Uncaught TypeError: Cannot destructure property 'attrs' of 'undefined' or 'null'.. Это понятно, потому что null и undefined нельзя привести к объектам. Что я могу сделать, чтобы защититься от этого?

Если в качестве второго аргумента передаются array, number и т. Д., Ошибка не выдается, поскольку они могут быть принудительно обработаны, и я могу затем обработать эти значения в теле функции. При работе с null или undefined код в функции никогда не выполняется.

// expected behaviour
createElement('div', []); // Uncaught Error: The options argument must be an object
createElement('div', function(){}); // Uncaught Error: The options argument must be an object
createElement('div', false); // Uncaught Error: The options argument must be an object
createElement('div', new Date()); // Uncaught Error: The options argument must be an object
createElement('div', 4); // Uncaught Error: The options argument must be an object

// unwanted behaviour
createElement('div', null); // Uncaught TypeError: Cannot destructure property `attrs` of 'undefined' or 'null'
createElement('div', undefined); // Uncaught TypeError: Cannot destructure property `attrs` of 'undefined' or 'null'

Отредактировано, чтобы обеспечить окончательное решение : После прочтения комментариев, кажется, что единственное решение - это разрешить выбрасывание исключения или деструктурировать код в теле функции и обработать ошибку. Это решение, которое я выбрал:

createElement (type, opts) {
  if (arguments[1] !== undefined && Object.prototype.toString.call(opts) !== '[object Object]') { 
    throw Error('The options argument must be an object'); 
  }

  const { attrs = {}, children = [] } = opts || {};

  return {
    type,
    attrs,
    children
  }
}

Ответы [ 4 ]

2 голосов
/ 11 апреля 2019

Эта функция, вероятно, делает то, что вы хотите (допустите значение по умолчанию для null или undefined второго аргумента):

function createElement (type, obj) {
  const arg1 = arguments[1];
  if (arg1 !== null && arg1 !== undefined &&
      Object.prototype.toString.call(arg1) !== '[object Object]') {
    throw Error('The options argument must be an object'); 
  }
  let { attrs = {}, children = [] } = obj || {}
  return {
    type,
    attrs,
    children
  }
}

Эта функция также исправляет работу вашего объектного теста.

[ОБНОВЛЕНО]

Если вы хотите, чтобы null также выдавал необъектную ошибку, вы можете использовать это:

function createElement (type, obj) {
  const arg1 = arguments[1];
  if (arg1 !== undefined &&
      Object.prototype.toString.call(arg1) !== '[object Object]') {
    throw Error('The options argument must be an object'); 
  }
  let { attrs = {}, children = [] } = obj || {}
  return {
    type,
    attrs,
    children
  }
}
2 голосов
/ 11 апреля 2019

Вы можете отложить деструктуризацию и пройти проверку заранее.

function createElement (type, object) {
   if (!object || typeof object !== 'object' || Array.isArray(object)) { 
       throw Error('The options argument must be an object'); 
   }
   var { attrs = {}, children = [] } = object;
   return { type, attrs, children };
}
1 голос
/ 11 апреля 2019

Я предложу деструктурировать внутреннюю функцию вместо того, чтобы делать это в определении функции

function createElement (type, obj) {
  let { attrs = {}, children = [] } = obj || {attrs:undefined,children:undefined}
  return {
    type,
    attrs,
    children
  }
}


console.log(createElement('some type',undefined))
1 голос
/ 11 апреля 2019

Со значениями по умолчанию.

function createElement(type, { attrs, children } = {}) {
  return {
    type,
    attrs,
    children
  }
}

console.log(createElement("foo"));
console.log(createElement("foo", undefined));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...