Issue 1:
Bug Report

Current Behavior

let a = {1: 'one', 2: 'two', 3:'three'};

const {1:val, ...aWithoutOne} = a;

console.log(val); // prints 'one'

console.log(aWithoutOne); // Expects {2:'two', 3:'three'} , gets {1: 'one', 2: 'two', 3:'three'};

Input Code

Run the code above in JSBin against Javascript and ES6/Babel to see the difference.

Expected behavior/code

A clear and concise description of what you expected to happen (or code).

The problem is because ObjectWithoutProperties uses a for(key in obj) loop and compares with the keys sent. Since the key here is a number and for..in returns string, the behavior is incorrect. It is different from a v8 implementation. Making matters worse, val is set correctly, which made it harder to debug.

Possible Solution

Convert the keys to string before passing to ObjectWithoutProperties() function

Additional context/Screenshots

Try the code in Babel REPL and observe the output difference in Chrome console from both side.

Issue 2:
Bug Report

Current Behavior

This was discovered a few days ago. We were using three “newer” JavaScript features:

Object destructuring

Rest properties

Computed property names

The following line (from the block below):

const { [person.id]: excludedPerson, ...includedPeople } = samePeople;

... will pick off the value and place it in excludedPerson, but fail to exclude that entry in includedPeople. This is only the case if person.id is passed in as a number, but if it is cast to a string then that property is (correctly) omitted in includedPeople.

Input Code

const people = {
21: {
id: 21,
name: 'Michelle Rodriguez',
},
22: {
id: 22,
name: 'Heath Ledger',
},
23: {
id: 23,
name: 'Jack the Ripper',
},
};

const id = 21;
const person = people[id];
const samePeople = { ...people };

const { [person.id]: excludedPerson, ...includedPeople } = samePeople;

console.log(excludedPerson, includedPeople);

Expected behavior/code

It would be expected that that the Michelle Rodriguez object would be omitted from includedPeople but it is still included in includedPeople.

Babel Configuration (.babelrc, package.json, cli command)

This can be replicated here: https://babeljs.io/repl

Environment

This can be replicated here: https://babeljs.io/repl

Possible Solution

Babel spits out the following code in order to omit properties from the rest object:

function _objectWithoutProperties(obj, keys) {
var target = {};
for (var i in obj) {
if (keys.indexOf(i) >= 0) continue;

// Excludes properties on the prototype chain.
if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
target[i] = obj[i];
}
return target;
}

If person.id is passed as a number (i.e. just as it is), then the keys.indexOf(i) >= 0 check fails, since the for..in loop will return the keys as strings. The keys parameter will be an Array of just one number (as per the above code), e.g. '21' will not be found inside [21]. Therefore the property does not get excluded from target and ends up in the rest object.

But if I cast to a string, e.g. `${person.id}`, String(person.id), person.id + '', Number(person.id).toString(), then the condition goes through.

Additional context/Screenshots

We ended up going with Lodash's omit in order to omit the chosen property, but a fix that worked was simply casting person.id to a string, e.g.

const id = 21;
const person = people[id];
const samePeople = { ...people };

const personId = `${person.id}`;

const { [personId]: excludedPerson, ...includedPeople } = samePeople;

At that point the omission works correctly.

The code seems to work correctly in the Chrome Console and the Node.js REPL, but fails when Babel transpiles it.