无法实现简单的可选链接

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

所以它只会更新传递的键和值,我希望问题不在打字稿上