【问题标题】:Javascript Object Paranoia (can I depend on order of elements)Javascript对象偏执狂(我可以依赖元素的顺序)
【发布时间】:2018-07-19 17:23:51
【问题描述】:

我有一个 javascript (node.js) 对象:

const fileObj = {filename: 'file1', filepath: '/file1/path/', flag: true,}

有人告诉我,对于对象,不能保证顺序(与明确排序的数组不同)——所以我可以确定

Object.values(fileObj)

将按照与键吐出相同的顺序吐出值

Object.keys(fileObj)

这很关键的原因是在节点中使用了 mysql 转义值:

const mysql = require('mysql');
const connection = mysql.createConnection(credentials); 

const fileObj = {filename: 'file1', filepath: '/file1/path/', flag: true,}
const cols = Object.keys(fileObj).join(', ');
const placeholder = Object.keys(fileObj).fill('?').join(', ');

const sql = `INSERT INTO table1 (${cols}) VALUES (${placeholder})`;

connection.query(sql, Object.values(fileObj), function (error, results, fields) {
    // Do stuff
});

这将创建一个 SQL 语句:

sql = INSERT INTO table1 (filename, filepath, flag) VALUES (?, ?, ?);

理论上然后与转义值相结合:

connection.query(sql, ['file1', '/file1/path/', true], function...

但如果它们的顺序不同,游戏就结束了......


相关问题:

Does JavaScript Guarantee Object Property Order?(Javscript 不保证订单...除非您可以期待订单...)

Does ES6 introduce a well-defined order of enumeration for object properties?(有时可以保证订单...但不能使用 Object.keys?)

它是什么?我应该使用什么来确保我的 mySQL 转义值与我的 mySQL 列名的顺序相同?

【问题讨论】:

  • 使用Object.entries()
  • 使用Object.entries 并映射两次!
  • 或者根据其他建议使用Object.entries,并使用INSERT... SET... SQL 语法映射一次。
  • Object.entries(yourObject) 不保证条目的顺序,但它确实保持键:值配对。
  • 根据一些参与编写 ES 规范的人的说法,语言并不能保证顺序,因为最后所有的 if x was invoked as 归结为一个根本没有指定顺序的内部方法跨度>

标签: javascript mysql node.js javascript-objects


【解决方案1】:

根据多个其他用户的建议,我会使用Object.entries

然后您可以选择继续提取键和值,这一次保证您的 SQL 语句中使用的顺序。

var attributes = {
  a: 'A',
  f: 'F',
  c: 'C',
  b: 'B',
  e: 'E',
  d: 'D',
};

const entries = Object.entries(attributes);
const keys = entries.map(entry => entry[0]);
const values = entries.map(entry => entry[1]);

console.log(keys, values);

【讨论】:

  • 所以 object.entries 每次被调用时都保证顺序?
  • Object.entries 返回一个数组键/值对数组。所以顺序实际上并不重要,因为键和值总是在一起的。
  • @fubar,既然你给Object.entries打了两次电话,他们可能每次来的顺序都不一样,对吧?
  • @KoshVery - 好声音。我已经更新了我的答案,叫它一次。
  • @Paulpro:不,ES6 引入了一个命令(例如,[[OwnPropertyKeys]] 紧随其后),但for in 被明确允许忽略它并执行实现定义的操作。 Object.keys/values/entries 都遵循实现定义的for in 顺序。 Reflect.ownKeys 是使用 ES6 顺序的一件事。
【解决方案2】:

您可以在一个循环中将您的对象转换为数组。它将保证正确的顺序:

const fileObj = {filename: 'file1', filepath: '/file1/path/', flag: true,}

const vals = [], placeholder = [];
const keys = Object.keys(fileObj).map(k => vals.push(fileObj[k]) && placeholder.push('?') && k);

console.log(`INSERT INTO table1 (${keys}) VALUES (${placeholder})`);
console.log(keys + ''); console.log(vals + '');

【讨论】:

  • 这是个好主意。使用单次迭代可确保键和值匹配。我们实际上不需要为此排序对象,我们只需要避免重复迭代。
  • 挖掘单迭代方法!
  • 如果您要丢弃map 的结果,也可以使用forEach
【解决方案3】:

如果你使用 mysql2 npm 包,你可以使用这个更好的语法。

const fileObj = {filename: 'file1', filepath: '/file1/path/', flag: true,}
const sql = `INSERT INTO table1 SET ?`;
const result = await connection.query(sql, [fileObj]);

【讨论】:

    【解决方案4】:

    我个人不会对对象使用任何骇人听闻的操作(其设计最初应该是键到值的无序映射),因为它们可以由实现定义(有时同一解释器的版本之间会有所不同)。

    如果您想订购,请使用数组:

    const fileObj = [
      {
        key: 'filename',
        val: 'file1'
      },
      {
        key: 'filepath',
        val: '/file1/path/'
      },
      {
        key: 'flag',
        val: true,
      }
    ];
    

    这是明确的,适用于 JS 的所有版本和实现。

    【讨论】:

    • 是的...但是如果数据以无序对象形式出现...将其放入有序数组中是诀窍。
    • @Trees4theForest 您可以使用单行 JavaScript 从对象字面量获取到上述结构:fileObj = Object.entries(fileObj).map(([key, value]) => ({key, value}));
    猜你喜欢
    • 2017-02-01
    • 2016-04-07
    • 2020-07-22
    • 2017-06-07
    • 1970-01-01
    • 2011-01-24
    • 1970-01-01
    • 1970-01-01
    • 2013-09-29
    相关资源
    最近更新 更多