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
5 Answers
Reset to default 3With 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条)