解构函数参数时如何处理“空”和“未定义”值

时间:2019-04-11 18:23:10

标签: javascript destructuring

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

5 个答案:

答案 0 :(得分:1)

使用默认值。

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

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

答案 1 :(得分:1)

我建议在函数内部进行结构分解,而不要在函数定义中进行

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


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

答案 2 :(得分:1)

您可以推迟销毁并提前检查。

var simService = new SimulationServiceClient(ServerAddress, null, null);

var request = new CreateSpectatorRequest();
request.setApi(API_VERSION);
request.setId(this.clientId);
var metadata = {};
var stream = simService.createSpectator(request, metadata);
stream.on("data", this.onData);
stream.on("status", this.onStatus);
stream.on("end", this.onEnd);

答案 3 :(得分:1)

此功能可能会满足您的要求(允许将nullundefined第二个arg作为默认参数):

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

答案 4 :(得分:0)

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