无法实现简单的可选链接
Can't implement simple optional chaining
我正在尝试实现一个简单的可选链接状态更新。我想要的是仅在项目为 defined/exists 时才更改项目;如果 not/is 未定义,我希望该项目保持以前的状态(例如,如果未更新,用户 ID 应保持 = 2)。
为了测试这一点,我创建了一个包含三个变量的对象:
const userObj = {
firstName: "",
lastName: "",
userID: 2,
};
然后我创建了一个函数来更新状态:
const updateState = (item) => {
return {
userObj.firstName = item?.firstName,
userObj.lastName = item?.lastName,
userObj.userID = item?.userID,
};
};
最后,我传递了仅包含一个要更新的项目 (firstName) 的项目,然后我调用函数:
const item = {
firstName: "None",
};
console.log(updateState(item));
输出:
userObj.firstName = item?.firstName,
^
SyntaxError: Unexpected token '.'
但是当我将鼠标悬停在 userObj
上时,我可以看到它的属性:
您可以将 空合并 与可选链接结合使用:
const updateState = item => ({
userObj.firstName = item?.firstName ?? userObj.firstName ,
userObj.lastName = item?.lastName ?? userObj.lastName ,
userObj.userID = item?.userID ?? userObj.userId ,
});
您可以使用 展开运算符:
const updateState = item => {
userObj = { ...userObj, ...item };
return userObj;
}
或者你可以使用lodash's defaults()
函数:
const _ = require('lodash');
const updateState = item => {
userObj = _.defaults(userObj, item)
return userObj;
}
或者......如果你真的想改变状态对象,而不是创建一个新的对象并替换它,那就自己动手吧,类似的:
const updateState = item => {
for (const key in item ) {
const hasValue = key != null && key != undefined && key != NaN ;
if ( hasValue ) {
userObj[prop] = item[prop];
}
}
}
正如他们所说,剥猫皮的方法不止一种。
[已编辑: 添加 spread 运算符的说明]
传播运算符,
const obj = { ...obj1, ...obj2, . . . , ...objN };
有点类似于调用这样的函数:
const obj = mergeObjects( obj1, obj2, . . ., objN );
其中 mergeObjects()
定义为:
function mergeObjects(...objects) {
const mergedObject = {};
for (const obj of objects ) {
for (const key in obj ) {
mergedObject[key] = item[key];
}
}
return mergedObject;
}
或者使用 Object.assign()
可能会有更好的解释。可以说这样的表达式:
const obj = {
prop1: 'a' ,
prop2: 'b' ,
...obj1 ,
prop3: 'c' ,
prop4: 'd' ,
...obj2 ,
prop5: 'e' ,
prop6: 'f' ,
...obj3 ,
}
相当于:
const obj = Object.assign( {},
{
prop1: 'a' ,
prop2: 'b' ,
},
obj1 ,
{
prop3: 'c' ,
prop4: 'd' ,
} ,
obj2 ,
{
prop5: 'e' ,
prop6: 'f' ,
} ,
obj3 ,
);
你得到这个错误是因为你试图 return 是一个在它的键中有点的对象。
您正在混合赋值和对象创建。此外 item?.firstName
仅在 item
为 null 或未定义的情况下有所帮助,因为它会快速失败而不是抛出异常,因为您无法访问 null.firstName
.
对于这种默认设置,您必须按照 typeof item.firstName === 'string' ? item.firstName : userObj.firstName
.
的方式进行操作
将所有内容整合在一起:
const func = (value, fallback) => (
typeof value === typeof fallback
? value
: fallback
);
const updateState = (item) => {
userObj.firstName = func(item?.firstName, item.firstName);
userObj.lastName = func(item?.lastName, item.lastName);
userObj.userID = func(item?.userID, item.userId);
return userObj;
};
但是请注意,此函数会发生变异 userObj
。
编辑:default
是一个糟糕的命名选择。
你可以这样做,使用javascript对象解构
const updateState = (item) => {
return {
...userObj,
...item,
};
};
所以它只会更新传递的键和值,我希望问题不在打字稿上
我正在尝试实现一个简单的可选链接状态更新。我想要的是仅在项目为 defined/exists 时才更改项目;如果 not/is 未定义,我希望该项目保持以前的状态(例如,如果未更新,用户 ID 应保持 = 2)。
为了测试这一点,我创建了一个包含三个变量的对象:
const userObj = {
firstName: "",
lastName: "",
userID: 2,
};
然后我创建了一个函数来更新状态:
const updateState = (item) => {
return {
userObj.firstName = item?.firstName,
userObj.lastName = item?.lastName,
userObj.userID = item?.userID,
};
};
最后,我传递了仅包含一个要更新的项目 (firstName) 的项目,然后我调用函数:
const item = {
firstName: "None",
};
console.log(updateState(item));
输出:
userObj.firstName = item?.firstName,
^
SyntaxError: Unexpected token '.'
但是当我将鼠标悬停在 userObj
上时,我可以看到它的属性:
您可以将 空合并 与可选链接结合使用:
const updateState = item => ({
userObj.firstName = item?.firstName ?? userObj.firstName ,
userObj.lastName = item?.lastName ?? userObj.lastName ,
userObj.userID = item?.userID ?? userObj.userId ,
});
您可以使用 展开运算符:
const updateState = item => {
userObj = { ...userObj, ...item };
return userObj;
}
或者你可以使用lodash's defaults()
函数:
const _ = require('lodash');
const updateState = item => {
userObj = _.defaults(userObj, item)
return userObj;
}
或者......如果你真的想改变状态对象,而不是创建一个新的对象并替换它,那就自己动手吧,类似的:
const updateState = item => {
for (const key in item ) {
const hasValue = key != null && key != undefined && key != NaN ;
if ( hasValue ) {
userObj[prop] = item[prop];
}
}
}
正如他们所说,剥猫皮的方法不止一种。
[已编辑: 添加 spread 运算符的说明]
传播运算符,
const obj = { ...obj1, ...obj2, . . . , ...objN };
有点类似于调用这样的函数:
const obj = mergeObjects( obj1, obj2, . . ., objN );
其中 mergeObjects()
定义为:
function mergeObjects(...objects) {
const mergedObject = {};
for (const obj of objects ) {
for (const key in obj ) {
mergedObject[key] = item[key];
}
}
return mergedObject;
}
或者使用 Object.assign()
可能会有更好的解释。可以说这样的表达式:
const obj = {
prop1: 'a' ,
prop2: 'b' ,
...obj1 ,
prop3: 'c' ,
prop4: 'd' ,
...obj2 ,
prop5: 'e' ,
prop6: 'f' ,
...obj3 ,
}
相当于:
const obj = Object.assign( {},
{
prop1: 'a' ,
prop2: 'b' ,
},
obj1 ,
{
prop3: 'c' ,
prop4: 'd' ,
} ,
obj2 ,
{
prop5: 'e' ,
prop6: 'f' ,
} ,
obj3 ,
);
你得到这个错误是因为你试图 return 是一个在它的键中有点的对象。
您正在混合赋值和对象创建。此外 item?.firstName
仅在 item
为 null 或未定义的情况下有所帮助,因为它会快速失败而不是抛出异常,因为您无法访问 null.firstName
.
对于这种默认设置,您必须按照 typeof item.firstName === 'string' ? item.firstName : userObj.firstName
.
将所有内容整合在一起:
const func = (value, fallback) => (
typeof value === typeof fallback
? value
: fallback
);
const updateState = (item) => {
userObj.firstName = func(item?.firstName, item.firstName);
userObj.lastName = func(item?.lastName, item.lastName);
userObj.userID = func(item?.userID, item.userId);
return userObj;
};
但是请注意,此函数会发生变异 userObj
。
编辑:default
是一个糟糕的命名选择。
你可以这样做,使用javascript对象解构
const updateState = (item) => {
return {
...userObj,
...item,
};
};
所以它只会更新传递的键和值,我希望问题不在打字稿上