获得财产比使用Lodash更好的方法

时间:2017-10-30 19:55:55

标签: javascript reactjs lodash

所以我们在代码中都有这个垃圾,IMO太多了。例如:

const profileId = _.get(account, 'profileId', null);
const player = _.get(someCustomObject, 'player'); // Why??????  why not just someCustomObject.player?
当你只能通过对象访问对象属性时,使用lodash是我还是荒谬的呢?一般来说,我们正在使用lodash,并且它在许多地方都是过度杀戮而且只是让你的代码更加冗长,并且当你拥有它时很难阅读。

在这种情况下,我们也不需要lodash:

const profileId = _.get(account, 'profileId', null);

没有lodash会怎样做?那是我的问题。以下是一些想法:

const profileId = (account && account.profileId) || null

还有其他想法吗?

更新

有趣的是,与Ori的答案一致,但这只是观察。我想删除将profileId默认为null只是因为我觉得它是不必要的。但为什么不将profileId设置为帐户对象?

const account = {};
const game = { player: 'Sam' }

console.log(`account: ${account}`);

const { profileId } = account || {};
const { player } = game || {};

console.log(`profileId: ${profileId} // why is this undefined if account has value {}???`);
console.log(`player: ${player}`);

即使帐户设置为文字,我仍然会获得上面的profileId undefined。这很奇怪..?

最终解决方案 (在codepen.io中运行,因为你需要加载lodash)

console.log(" Example Clean Code without Lodash")
console.log('===============================')

let account = {};
const game = { player: 'Sam' }

console.log(`account: ${account}`);

const { profileId = null } = account;
const { player } = game || {};

console.log(`profileId: ${profileId}`);
console.log(`player: ${player}`);

/* using IIFE so profileId doesn't conflict with example above */
(() => {
  console.log("Example using unecessary Lodash")
  console.log('===============================')

  let profileId = _.get(account, 'profileId', null);
  const game = { player: 'Sam' } 

  console.log(`account2: ${account}`);

  const { player } = game || {};

  console.log(`profileId: ${profileId}`);
  console.log(`player: ${player}`);
})();

4 个答案:

答案 0 :(得分:4)

Lodash的_.get()非常好,如果你想在对象profile.player.id中嵌套一些东西,如果没有找到任何东西或者有错误,它也有一个默认值,例如这个例子{{ 1}}。

如果它是对象的直接属性,则可以使用destructuring with a default

_.get(account, 'profileId', null);

更好的解决方案可能是stage-1 proposal-optional-chaining如果它符合规范,尽管你现在可以将它与babel插件一起使用:

const account = {};
const game = { player: 'Sam' }


const { profileId = null } = account || {};
const { player } = game || {};

console.log(profileId);
console.log(player);

答案 1 :(得分:2)

_.get是一种辅助方法,出于多种原因使用。它可以帮助您减少代码/逻辑重复,更难以发生错误,更容易阅读和维护代码。

如果您担心_.get(account && account.profileId) || null之间的性能差异,我认为您不应该担心,除非您有一个庞大的代码库,可以调用_.get次数。这是lodash的get函数定义及其依赖性。

function get(object, path, defaultValue) {
  var result = object == null ? undefined : baseGet(object, path);
  return result === undefined ? defaultValue : result;
}

function baseGet(object, path) {
  path = castPath(path, object);

  var index = 0,
      length = path.length;

  while (object != null && index < length) {
    object = object[toKey(path[index++])];
  }
  return (index && index == length) ? object : undefined;
}

function castPath(value, object) {
  if (isArray(value)) {
    return value;
  }
  return isKey(value, object) ? [value] : stringToPath(toString(value));
}

function toKey(value) {
  if (typeof value == 'string' || isSymbol(value)) {
    return value;
  }
  var result = (value + '');
  return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
}

您始终可以使用2种不同的变体对代码执行基准测试,然后确定它是否足以让您使用本机实现。

我刚做了基准测试,其中lodash的._get 95%比本机实现慢。我想你可以负担得起,除非你的代码严重依赖._get如上所述。 也许更好的选择是编写自己的辅助函数来摆脱lodash的开销,并实现lodash的get和近原生性能的相同优点。您可以预先知道自己的帮助函数,知道将传递给它的数据类型,从而为您的特定用例编写零开销助手。

答案 2 :(得分:0)

这是“ Safely Accessing Deeply Nested Values In JavaScript”一文中不错的一句话。

export function _get(object, path, defval = null) {
    if (typeof path === "string") path = path.split(".");
    return path.reduce((xs, x) => (xs && xs[x] ? xs[x] : defval), object);
}

答案 3 :(得分:0)

这是从最近的一次讨论中得出的:

var template = "string with {obj.prop} first of 0: {results[0].first}";
var data = {obj: {prop: 'mine'}, results:[{first:'f'},{first:'ff'}] }
var regex = /{(.*?)}/g;
var str = template.replace(regex, (e, key) => _.get(data, key, ''));
console.log(str);

但是您可以编写一个函数:

const interpolate = (template, data) => template.replace(/{(.*?)}/g, (e, key) => _.get(data, key, ''));

当然,它更易于使用:

let str = interpolate("string with {obj.prop} first of 0: {results[0].first}", data)

通常,在您不知道要替换什么的任何地方,_.get()都是不错的选择。

更新:修复缺少的正则表达式!