Coffeescript one liner for creating hashmap with variable key - javascript

Is it possible to do the following in one line in coffeescript?
obj = {}
obj[key] = value
I tried:
obj = { "#{key}": value }
but it does not work.

It was removed from the language
Sorry for being tardy -- if I remember correctly, it was because some
of our other language features depend on having the key known at
compile time. For example, method overrides and super calls in
executable class bodies. We want to know the name of the key so that a
proper super call can be constructed.
Also, it makes it so that you have to closure-wrap objects when used
as expressions (the common case) whenever you have a dynamic key.
Finally, there's already a good syntax for dynamic keys in JavaScript
which is explicit about what you're doing: obj[key] = value.
There's something nice about having the {key: value, key: value} form
be restricted to "pure" identifiers as keys.

(obj = {})[key] = value
will compile to
var obj;
(obj = {})[key] = value;
This is normal javascript. The only benefit you get from coffeescript is that you don't have to pre-declare var s because it does it for you.

For anyone that finds this question in the future, as of CoffeeScript 1.9.1 interpolated object literal keys are once again supported!
The syntax looks like this:
myObject =
a: 1
"#{ 1 + 2 }": 3
See https://github.com/jashkenas/coffeescript/commit/76c076db555c9ac7c325c3b285cd74644a9bf0d2

Depending on how complex your key is you can always use a variable name matching your key and use it to define an object, like this:
myKey = "Some Value"
obj = {myKey}
Which will compile to:
var myKey, obj;
myKey = "Some Value";
obj = {
myKey: myKey
};
So what you end up with is something close to what you seek, but that requires your keys to be valid variable names.

If you're using underscore, you can use the _.object function, which is the inverse of the _.pairs function.
_.pairs({a: 1, b: 'hello'})
//=> [['a', 1], ['b', 'hello']]
_.object([['a', 1], ['b', 'hello']])
//=> {a: 1, b: 'hello'}
So, assuming myKey = 'superkey' and myValue = 100 you could use:
var obj = _.object([[myKey, myValue]]);
//=> obj = {superkey: 100}

Related

Unlike Java, does an assignment operator in Javascript mean that all operations on the LHS are reflected for the RHS?

This is in continuation to the answer posted for the question "Convert JavaScript dot notation object to nested object".
The code works like a charm but I'm unable to wrap my head around how!! So a few days later + a situation where my console.logs actually exceed my lines of code :P.. Here's my question:
Below code for JavaScript function:
function deepen(o) {
var oo = {}, t, parts, part;
for (var k in o) {
t = oo;
parts = k.split('.');
var key = parts.pop();
while (parts.length) {
part = parts.shift();
t = t[part] = t[part] || {};
}
t[key] = o[k]
}
return oo;
}
console.log(
deepen({ 'ab.cd.e' : 'foo', 'ab.cd.f' : 'bar', 'ab.g' : 'foo2' })
);
It deepens a JSON object from :
{
'ab.cd.e' : 'foo',
'ab.cd.f' : 'bar',
'ab.g' : 'foo2' }
Into a nested object :
{ab: {cd: {e:'foo', f:'bar'}, g:'foo2'}}
I get the part where for each key value pair, the logic pops the last element post splitting into an array by ".".
That becomes the key.
What I'm not understanding is the below.
1) The function is returning 'oo' but the operations are all on 't'. The only relationship is that t is being assigned the'empty object' "oo" at the beginning of every iteration on the flat JSON.
2) after the "while (parts.length)" loop, oo miraculously has the nested structure whereas t has one level below it. if oo is assigned to t, how is that possible?
3) I don't see the function being called recursively. How is 00 getting nested beyond the first element of the flat JSON?
I'll first redefine the function with some better names, this way explanation is a lot easier to do.
function deepen(object) {
var nestedObject = {}, cursor, nestingPath, nodeKey;
for (var dotKey in object) {
cursor = nestedObject;
nestingPath = dotKey.split('.');
var leafKey = nestingPath.pop();
while (nestingPath.length) {
nodeKey = nestingPath.shift();
cursor = cursor[nodeKey] = cursor[nodeKey] || {};
}
cursor[leafKey] = object[dotKey];
}
return nestedObject;
}
My guess is that don't entirely know how the while loop functions. Important to know is that when two variables refer to the same object both change when you change one. They are the same object, but you've chosen to have two handles.
Let me provide an example:
object = {};
cursor = object;
cursor.foo = "bar";
object; //=> {foo: "bar"}
cursor; //=> {foo: "bar"}
cursor.a = {};
object; //=> {foo: "bar", a: {}}
cursor; //=> {foo: "bar", a: {}}
cursor = cursor.a;
object; //=> {foo: "bar", a: {}}
cursor; //=> {} <- this is ^
cursor.b = "c";
object; //=> {foo: "bar", a: {b: "c"}}
cursor; //=> {b: "c"}
The while loop is mostly based upon this principal. It's not easy to explain, but I hope the above clarifies things.
Another thing that might be confusing is the line:
cursor = cursor[nodeKey] = cursor[nodeKey] || {};
// read as
cursor = (cursor[nodeKey] = (cursor[nodeKey] || {}));
This could also be written as:
if (!cursor[nodeKey]) cursor[nodeKey] = {};
cursor = cursor[nodeKey];
This assigns a new object to the dynamic nodeKey property if the property isn't there (falsy). Then cursor is assigned to the nested object within, similar to my example above cursor = cursor.a.
First, you're not working with JSON, but a JS object. Most of the time, you should see object as HashMap<String, HashMap<String, ...>> ad infinitum, if you need a Java analogy.
Your questions:
t = oo means they both refer to the same instance created at the start of the function. Why do you use a second variable?
t = t[part] You literally assign entry of t to t
I didn't test the code, but I'm pretty sure it's buggy. Test what happens with object that have multiple names in top level, eg. {'a.b':1, 'b.a':1}. You don't need recursion though, you could use stack instead.
Regarding your code:
Use descriptive names and comments, especially when asking question where other people need to understand your code
Do not define all variables at the beginning of the function. That old habit comes from the dawn of C language and needs to die
for (var k in o) is not a recommended approach to iterate over object entries. Use Object.entries
There is no need to pop from parts array, it is reset every iteration. for(const part of parts) would work just as well

React syntax explanation for setState [duplicate]

Can anyone explain how the why/how the below method of assigning keys in JavaScript works?
a = "b"
c = {[a]: "d"}
return:
Object {b: "d"}
It's the new ES2015 (the EcmaScript spec formally known as ES6) computed property name syntax. It's a shorthand for the someObject[someKey] assignment that you know from ES3/5:
var a = "b"
var c = {[a]: "d"}
is syntactic sugar for:
var a = "b"
var c = {}
c[a] = "d"
Really the use of [] gives an excellent way to use actual value of variable as key/property while creating JavaScript objects.
I'm pretty much statisfied with the above answer and I appreciate it as it allowed me to write this with a little example.
I've executed the code line by line on Node REPL (Node shell).
> var key = "fullName"; // Assignment
undefined
>
> var obj = {key: "Rishikesh Agrawani"} // Here key's value will not be used
undefined
> obj // Inappropriate, which we don't want
{ key: 'Rishikesh Agrawani' }
>
> // Let's fix
undefined
> var obj2 = {[key]: "Rishikesh Agrawani"}
undefined
> obj2
{ fullName: 'Rishikesh Agrawani' }
>
const animalSounds = {cat: 'meow', dog: 'bark'};
const animal = 'lion';
const sound = 'roar';
{...animalSounds, [animal]: sound};
The result will be
{cat: 'meow', dog: 'bark', lion: 'roar'};
Also, only condition to use [] notation for accessing or assigning stuff in objects when we don't yet know what it's going to be until evaluation or runtime.
I want to make an object but I don't know the name of the key until runtime.
Back in the ES5 days:
var myObject = {};
myObject[key] = "bar";
Writing two lines of code is so painful... Ah, ES6 just came along:
var myObject = {[key]:"bar"};
If the value of key equals foo, then both approaches result in:
{foo : "bar"}

What is the Javascript equivalent of Python's get method for dictionaries

Python's get method for dictionaries lets me specify what should be returned if a key doesn't exist. For my current case I want a dictionary returned. How do I do this in Javascript?
There is no javascript equivalent of the python dictionary get method. If you would write it yourself, as a function, it would look like this:
function get(object, key, default_value) {
var result = object[key];
return (typeof result !== "undefined") ? result : default_value;
}
Use it like:
var obj = {"a": 1};
get(obj, "a", 2); // -> 1
get(obj, "b", 2); // -> 2
Note that the requested key will also be found in a prototype of obj.
If you really want a method rather than a function (obj.get("a", 2)), you need to extend the prototype of Object. This is generally considered a bad idea though, see Extending Object.prototype JavaScript
With modern javascript you can use the nullish coalescing operator ??
const result = obj[key] ?? default;
This will return the default value if key doesn't exist in obj. It will also return the default in cases like {myKey: undefined} or {myKey: null}, which may or may not be the desired behavior.
JavaScript has no helper feature to do that. You need to test explicitly.
if ("myProperty" in myObject) {
return { another: "object" };
} else {
return myObject.myProperty;
}
You can use a ternary operator to do the same thing with less code.
return ("myProperty" in myObject) ? myObject.myProperty : { another: "object" };
I prefer to use the logical OR like this:
foo.bar || 'default'
If checks is foo.bar is falsy, so it returns 'default' if bar is undefined.
You just need to care, that foo is an object. Otherwise a ReferenceError is thrown.
You could use a proxy for this (really new ):
var handler = {
get: function(target, name){
return name in target?
target[name] :
"Default";
}
};
var dictionary={"hi":true};
var dict = new Proxy(dictionary, handler);
dict.a = 1;
dict.b = undefined;
console.log(dict.a, dict.b,dict.hi); // 1, undefined,true
console.log(dict.new); //"Default"
//the proxied object gets changed:
console.log(dictionary.a, dictionary.b,dictionary.hi); // 1, undefined,true
console.log(dictionary.new); //undefined
A proxy is an object that reflects all changes and requests trough an handler. In this case we can write/access propertys of dictionary normally, but if we access values that do not exist it'll return "Default"
this works for me
let obj = {"a": 1};
let default = 100
obj["a"] || default; // -> 1
obj["b"] || default; // -> 100
But! there are some limitation, if !!obj["a"] === false we always get default value... so it's better to just check if key in obj, to be completely sure.

Loop through properties in JavaScript object with Lodash

Is it possible to loop through the properties in a JavaScript object? For instance, I have a JavaScript object defined as this:
myObject.options = {
property1: 'value 1',
property2: 'value 2'
};
Properties will get dynamically added to this object. Is there a way for me to just loop through and do a check if a property exists? If so, how?
Use _.forOwn().
_.forOwn(obj, function(value, key) { } );
https://lodash.com/docs#forOwn
Note that forOwn checks hasOwnProperty, as you usually need to do when looping over an object's properties. forIn does not do this check.
Yes you can and lodash is not needed... i.e.
for (var key in myObject.options) {
// check also if property is not inherited from prototype
if (myObject.options.hasOwnProperty(key)) {
var value = myObject.options[key];
}
}
Edit: the accepted answer (_.forOwn()) should be https://stackoverflow.com/a/21311045/528262
For your stated desire to "check if a property exists" you can directly use Lo-Dash's has.
var exists = _.has(myObject, propertyNameToCheck);
You can definitely do this with vanilla JS like stecb has shown, but I think each is the best answer to the core question concerning how to do it with lodash.
_.each( myObject.options, ( val, key ) => {
console.log( key, val );
} );
Like JohnnyHK mentioned, there is also the has method which would be helpful for the use case, but from what is originally stated set may be more useful. Let's say you wanted to add something to this object dynamically as you've mentioned:
let dynamicKey = 'someCrazyProperty';
let dynamicValue = 'someCrazyValue';
_.set( myObject.options, dynamicKey, dynamicValue );
That's how I'd do it, based on the original description.
Lets take below object as example
let obj = { property1: 'value 1', property2: 'value 2'};
First fetch all the key in the obj
let keys = Object.keys(obj) //it will return array of keys
and then loop through it
keys.forEach(key => //your way)
just putting all together
Object.keys(obj).forEach(key=>{/*code here*/})
In ES6, it is also possible to iterate over the values of an object using the for..of loop. This doesn't work right out of the box for JavaScript objects, however, as you must define an ##iterator property on the object. This works as follows:
The for..of loop asks the "object to be iterated over" (let's call it obj1 for an iterator object. The loop iterates over obj1 by successively calling the next() method on the provided iterator object and using the returned value as the value for each iteration of the loop.
The iterator object is obtained by invoking the function defined in the ##iterator property, or Symbol.iterator property, of obj1. This is the function you must define yourself, and it should return an iterator object
Here is an example:
const obj1 = {
a: 5,
b: "hello",
[Symbol.iterator]: function() {
const thisObj = this;
let index = 0;
return {
next() {
let keys = Object.keys(thisObj);
return {
value: thisObj[keys[index++]],
done: (index > keys.length)
};
}
};
}
};
Now we can use the for..of loop:
for (val of obj1) {
console.log(val);
} // 5 hello
It would be helpful to understand why you need to do this with lodash. If you just want to check if a key exists in an object, you don't need lodash.
myObject.options.hasOwnProperty('property');
If your looking to see if a value exists, you can use _.invert
_.invert(myObject.options)[value]
If you just want to loop through to map property values then use _.mapValues
If you are checking, if the property exists in the object as stated in the question asked, you can use lodash libray _.has method
_.has(object, path)
Let me give you an example, how to use it.
consider an object
const user = {
name : "prabhat",
age: 27,
height: "5.7"
}
if you want to check, if name property exist in the object,you can use _.has method as follows
_.has(user, 'name') //true
_.has(user, 'address') //false
you will get a boolean true/false in return.

How to get the value of key a and 'a' in javascript

How to get the value of key a and 'a' in javascript?
var obj = {a:1,'a':2}
The first key a will be overwritten by the second 'a'.
obj.a will return 2.
If your key name is a valid Javascript identifier or a number, Javascript will allow you to omit the quotes in key names. In practice, however, it's probably better to train yourself to always use quotes, to avoid confusion like this, and also because JSON requires them.
You can't - they are same key, and that initialiser will create an object with a single element 'a' with value '2'. Try this:
var obj = {a:1,'a':2};
for ( var i in obj )
{
alert(i + '=' + obj[i] );
}
And you'll just get "a=2' in response.
obviously, 'a' is the one-character string with a lowercase a as content; but what do you expect to be the other key? if you want it to be the value of a variable called a, then the curly braces syntax won't help you. Unlike Python, this syntax assumes the keys are strings, and quotes are optional.
You'd have to do something like this:
var a = 'givenkey'
var obj = {}
obj[a] = 1
obj['a'] = 2
this would create an object equivalent to:
var obj = {'givenkey':1, 'a':2}
If you not sure about key - use iteration
for(var k in obj)
alert(k + "=" + obj[k])
When you know key exact value use obj[k]
There isn't any difference.
alert([
obj.a,
obj['a']
].join("\n")); // returns 2 in both cases

Categories