Search code examples
javascriptmysqlnode.jsjavascript-objects

Javascript Object Paranoia (can I depend on order of elements)


I have a javascript (node.js) object:

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

With objects, I was told there is no guarantee of order (unlike arrays which are explicitly ordered) -- So can I be certain that

Object.values(fileObj)

will spit out the values in the same order as the keys spit out with

Object.keys(fileObj)

The reason this is critical is using mysql escaped values in node:

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

This creates a SQL statement:

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

Which theoretically is then coupled with the escape values:

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

But if they are not all in the same order, game over...


Related questions:

Does JavaScript Guarantee Object Property Order? (Javscript does not guarantee order... except maybe you can expect order...)

Does ES6 introduce a well-defined order of enumeration for object properties? (Order guaranteed sometimes... but not with Object.keys?)

Which is it? And what should I be using to make sure my mySQL escape values are in the same order as my mySQL column names?


Solution

  • I would use Object.entries per the suggest of multiple other users.

    You can then choose to continue to extract the keys and values, this time with the order guaranteed for use in your SQL statement.

    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);