解构函数参数时如何处理 "null" 和 "undefined" 值

How to handle "null" and "undefined" values when destructuring function arguments

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

但是如果将 nullundefined 作为参数传递,则会出现此错误:Uncaught TypeError: Cannot destructure property 'attrs' of 'undefined' or 'null'.。这是可以理解的,因为 nullundefined 不能强制转换为对象。我该怎么做才能防止这种情况发生?

如果 arraynumber 等作为第二个参数传递,则不会抛出任何错误,因为它们可以被强制转换,然后我可以在函数体中处理这些值。在处理 nullundefined 时,函数中的代码永远不会执行。

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

有默认值。

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

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

我建议在函数内部解构而不是在函数定义中解构

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


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

你可以推迟解构,提前检查一下。

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

这个函数可能会做你想要的(允许 nullundefined 第二个参数被默认):

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