javascript - How to handle "null" and "undefined" values when destructuring function argumen

function createElement (type, { attrs = {}, children = [] }) {if (Object.prototype.toString.call(argume

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
 }
}

I have a function which takes two arguments: a string and an object. In the function declaration, I am unpacking the object's values through destructuring.

When it es to making sure the second argument is an object, I know I can do this check: Object.prototype.toString.call(arguments[1] !== 'object Object').

But if null or undefined are passed as arguments, this error occurs: Uncaught TypeError: Cannot destructure property 'attrs' of 'undefined' or 'null'.. This is understandable because null and undefined cannot be coerced into objects. What can I do to guard against this?

If an array, number etc is passed as a second argument, no error is thrown because they can be coerced and I can then handle those values in the function body. When dealing with null or undefined, the code in the function is never executed.

// 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'

Edited to provide final solution: After reading the ments, it appears the only solution is either to allow the exception to be thrown or to destructure the code in the function body and handle the error. This is the solution I have chosen:

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
  }
}
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
 }
}

I have a function which takes two arguments: a string and an object. In the function declaration, I am unpacking the object's values through destructuring.

When it es to making sure the second argument is an object, I know I can do this check: Object.prototype.toString.call(arguments[1] !== 'object Object').

But if null or undefined are passed as arguments, this error occurs: Uncaught TypeError: Cannot destructure property 'attrs' of 'undefined' or 'null'.. This is understandable because null and undefined cannot be coerced into objects. What can I do to guard against this?

If an array, number etc is passed as a second argument, no error is thrown because they can be coerced and I can then handle those values in the function body. When dealing with null or undefined, the code in the function is never executed.

// 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'

Edited to provide final solution: After reading the ments, it appears the only solution is either to allow the exception to be thrown or to destructure the code in the function body and handle the error. This is the solution I have chosen:

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
  }
}
Share Improve this question edited Apr 11, 2019 at 19:45 Carl Mungazi asked Apr 11, 2019 at 18:23 Carl MungaziCarl Mungazi 958 bronze badges 6
  • please add some examples of the call and the wanted results. – Nina Scholz Commented Apr 11, 2019 at 18:26
  • If you want to handle the error why not a Try catch? – JRK Commented Apr 11, 2019 at 18:30
  • Done - thanks for highlighting that. – Carl Mungazi Commented Apr 11, 2019 at 18:31
  • @JRK a try/catch will not work because in the scenario I have described, the code in the function body is never executed. – Carl Mungazi Commented Apr 11, 2019 at 18:32
  • Why do you even want to guard against this? You want an exception to be thrown, right? – Bergi Commented Apr 11, 2019 at 18:56
 |  Show 1 more ment

5 Answers 5

Reset to default 3

With default values.

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

console.log(createElement("foo"));
console.log(createElement("foo", undefined));

This function probably does what you want (allow a null or undefined second arg to be defaulted):

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
  }
}

This function also fixes your object test to work properly.

[UPDATED]

If you do want null to also throw the non-object Error, you can use this:

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
  }
}

You could defer the destructuring and take a check in advance.

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 };
}

I will suggest to destructure inside function instead of doing it in definiation of function

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


console.log(createElement('some type',undefined))

In case when object is undefined use {property1,property2}={}

In case when property is undefined use {property1={},property2={}}

In your case object is undefined so below code will be used:

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
 }
}

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744407424a4572704.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信