template literals giving different answer - javascript

I'am javascript beginner trying to code to improve myself, at the moment trying to learn 'template literals' and for some reason getting different answer by putting inside 'template literals'. Here is my code :
const foodArray = [
{ name: 'Burrito' },
{ name: 'Pizza' },
{ name: 'Burger' },
{ name: 'Pasta' }
];
for (let i = 0; i < foodArray.length; i++) {
console.log(`i value: ${i} | Food Name:`, foodArray[i]);
}
<p id="demo"></p>
so now i'm putting 'foodArray[i]' inside 'template literals' like this ' ${foodArray[i] ' but it is giving me '[object Object]', shouldn't it give same result ? maybe i'm doing something wrong here
const foodArray = [
{ name: 'Burrito' },
{ name: 'Pizza' },
{ name: 'Burger' },
{ name: 'Pasta' }
];
for (let i = 0; i < foodArray.length; i++) {
console.log(`i value: ${i} | Food Name: ${foodArray[i]}`);
}
<p id="demo"></p>

console.log is going to do things differently than the template literal. the console.log will send the actual object reference to the console client and the particular console client will decide from there how to present that object, they all do it slightly differently. template literals will always call the objects .toString() method. some console clients just call the .toString() method as well, some use JSON.stringify, some use sophisticated object explorers, the SO console client uses some method to produce "pretty" JSON.
you can get it closer to the console representation or at least make it consistent by using JSON.stringify:
console.log(`i value: ${i} | Food Name: ${JSON.stringify(foodArray[i])}`);
but generally, in real world programming, you won't be sending objects to a template literal, so this isn't a huge concern in most applications.

Related

Make a new JS Object using an old one, see description for example

This one is pretty straight forward, I think I just don't know what tool to use. I've got an object which looks like this:
{
email: "email#aol.com", phone: "222-333-4444"
}
i am looking to convert it to the following array with nested objects
[
{
name: "email", value: "email#aol.com"
},
{
name: "phone", value: "222-333-4444"
},
]
im familiar with .map() and Oject.keys, just keep running into a wall on this one.
this is what i've been trying but im getting syntax errors
const data = Object.keys(data).map(key => {name: key, value: data[key]});
can anyone help? hopefully some quick points for someone. thanks!
To return object from arrow function, you must wrap it in () doc
To return an object literal expression requires parentheses around expression
const data = {
email: "email#aol.com", phone: "222-333-4444"
};
const result = Object.keys(data).map(key => ({name: key, value: data[key]}));

How to update all the values of a nested object in react or JavaScript

What is the appropriate way to update all the value of a nested dictionary.
Let's assume that I have this object:
someObj = {
0: {
message: 'Some text',
},
1: {
message: 'Other text',
},
}
If I just needed to update the first message on the object I would do something like:
someObj[0].message = 'New Message'
but what I want to achieve is to update all the message value in the object with one specific text.
What is the right way to achieve the above?
You can try with Object.keys(), see from the documentation:
The Object.keys() method returns an array of a given object's own enumerable property names, iterated in the same order that a normal loop would.
const someObj = { 0: { message: 'Some text', }, 1: { message: 'Other text', },}
Object.keys(someObj)
.forEach(e => {
someObj[e].message = 'new_text'
})
console.log(someObj)
+1 out of scope update:
There was an interesting question from #IsraGab in the comment section why to use this solution over for..in.
So I took a look at some benchmark to compare the speed of both of the solutions. Interestingly Object.keys().forEach() solution is usually 20% more faster comparing with for..in in this scenario.
See the benchmark's result below:
Run the comparison from here: https://jsbench.me/05khwctt9o
Use a for in loop
for(let prop in object){
object[prop].message = 'Your string';
}
someObj = {
0: {
message: 'Some text',
},
1: {
message: 'Other text',
},
}
for(let prop in someObj){
someObj[prop].message = 'your string';
}
console.log(someObj)
const keys = Object.keys(someObj);
for(let i = 0; i < keys.length; i++) {
someObj[keys[i]].message = 'Your string';
}

What is the ideal way to transform an object into an array holding multiple objects in Javascript? (ES6 allowed)

I have an object like so:
foo: {
someGuid: someString,
someGuid: someString,
someGuid: someString
}
I'm trying to figure out the best ways to insert it into an existing object as an array of objects as id/value pairs:
bar: {
someOtherInfo: someOtherValue,
someOtherInfo: someOtherValue,
baz: [
{
id: someGuid,
value: someString
},
{
id: someGuid,
value: someString
},
{
id: someGuid,
value: someString
}
]
}
I'm really interested in figuring out the best ways to accomplish this. By "best," I mean a good balance between code clarity/simplicity and performance (or all of the above if that's possible).
I know there's multiple approaches to take to transforming this data, so I'm really curious what others have come up with, I feel this would be a good learning opportunity for myself and others.
Also, this is in a Vue app, if that makes a difference. (I don't think there's a vue-specific way to do this, but if there is, I'm definitely interested in hearing how!)
The approach I've come up with so far has not worked, but here it is for those interested. I believe I'm going about it all wrong (probably overcomplicating it).
my data:
originalObject: {
someGuid: someString,
someGuid: someString,
someGuid: someString
}
newObject: {
some: null,
other: '1',
stuff: null,
irrelevant: null,
toThis: null,
problem: null,
targetArray: [
{},
],
},
my logic:
someFunction() {
const foo = this.originalObject;
const bar = this.newObject.targetArray;
const fooLength = Object.keys(foo).length;
Object.keys(foo).forEach(function (key) {
for (let i = 0; i < fooLength; i++) {
const foobar = bar[i];
console.log(foobar.ItemAttributeId);
console.log(foobar.Value);
foobar.ItemAttributeId = key;
foobar.Value = foo[key];
bar.push({ ItemAttributeId: foobar.ItemAttributeId, Value: foobar.Value });
}
});
},
So I feel like I'm making this more complex than it needs to be. Furthermore, the resulting output is incorrect (I'm somehow returning the value multiple times, but it seems a random number of multiples...sometimes it returns 4 times, sometimes 3, I'm trying to reason through why that is). I feel like there's just a better way to start out and I missed it, and now I'm down a rabbit hole.
In Vue, you would use a computed property.
console.clear()
new Vue({
el: "#app",
data:{
foo: {
someGuid1: "someString",
someGuid2: "someString",
someGuid3: "someString"
}
},
computed: {
baz(){
// nothing special here-- just javascript
return Object.entries(this.foo).map(([key,val]) => ({id: key, value: val}))
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.min.js"></script>
<div id="app">
{{baz}}
</div>
To add the array to some other object:
console.clear()
new Vue({
el: "#app",
data:{
foo: {
someGuid1: "someString",
someGuid2: "someString",
someGuid3: "someString"
}
},
computed: {
bar(){
// nothing special here-- just javascript
return {
some: "other",
props: "that don't matter",
baz: Object.entries(this.foo).map(([key,val]) => ({id: key, value: val}))
}
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.min.js"></script>
<div id="app">
<pre>
{{bar}}
<pre>
</div>
You can use Array.reduce along with Object.keys:
this.newObject.targetArray = Object.keys(this.originalObject).reduce((array, key) => {
array.push({
id: key,
value: this.originalObject[key],
})
return array
},[])
I believe there are two "popular" ways of doing this.
// You have this
const input = {
foo: {
someGuid1: "someString1",
someGuid2: "someString2",
someGuid3: "someString3"
}
}
// You want this:
[
{id: "someGuid1", value: "someString1"},
{id: "someGuid2", value: "someString2"},
{id: "someGuid3", value: "someString3"}
];
The imperative way:
const baz = [];
for (const [id, value] of Object.entries(input.foo)) {
baz.push({ id, value });
}
The functional way:
const baz = Object.entries(input.foo).map(([id, value]) => ({ id, value }));
In my opinion, you should always follow the style of the codebase you are working with if there is one, or the one you feel more comfortable with if there is no existing code.

Chai - Testing for values in array of objects

I am setting up my tests for the results to a REST endpoint that returns me an array of Mongo database objects.
[{_id: 5, title: 'Blah', owner: 'Ted', description: 'something'...},
{_id: 70, title: 'GGG', owner: 'Ted', description: 'something'...}...]
What I want my tests to verify is that in the return array it conatins the specific titles that should return. Nothing I do using Chai/Chai-Things seems to work. Things like res.body.savedResults.should.include.something.that.equals({title: 'Blah'}) error out I'm assuming since the record object contains other keys and values besides just title.
Is there a way to make it do what I want? I just need to verify that the titles are in the array and don't care what the other data might be (IE _id).
Thanks
This is what I usually do within the test:
var result = query_result;
var members = [];
result.forEach(function(e){
members.push(e.title);
});
expect(members).to.have.members(['expected_title_1','expected_title_2']);
If you know the order of the return array you could also do this:
expect(result).to.have.deep.property('[0].title', 'expected_title_1');
expect(result).to.have.deep.property('[1].title', 'expected_title_2');
As stated here following code works now with chai-like#0.2.14 and chai-things. I just love the natural readability of this approach.
var chai = require('chai'),
expect = chai.expect;
chai.use(require('chai-like'));
chai.use(require('chai-things')); // Don't swap these two
expect(data).to.be.an('array').that.contains.something.like({title: 'Blah'});
Probably the best way now a days would be to use deep.members property
This checks for unordered complete equality. (for incomplete equality change members for includes)
i.e.
expect([ {a:1} ]).to.have.deep.members([ {a:1} ]); // passes
expect([ {a:1} ]).to.have.members([ {a:1} ]); // fails
Here is a great article on testing arrays and objects
https://medium.com/building-ibotta/testing-arrays-and-objects-with-chai-js-4b372310fe6d
DISCLAIMER: this is to not only test the title property, but rather a whole array of objects
ES6+
Clean, functional and without dependencies, simply use a map to filter the key you want to check
something like:
const data = [{_id: 5, title: 'Blah', owner: 'Ted', description: 'something'},{_id: 70, title: 'GGG', owner: 'Ted', description: 'something'}];
expect(data.map(e=>({title:e.title}))).to.include({title:"Blah"});
or even shorter if you only check one key:
expect(data.map(e=>(e.title))).to.include("Blah");
https://www.chaijs.com/api/bdd/
Here is another approach that I found to be more helpful. Basically, use string interpolation and map your array of objects to an array of string literals. Then you can write expectations against the array of strings.
const locations: GeoPoint[] = [
{
latitude: 10,
longitude: 10
},
{
latitude: 9,
longitude: 9
},
{
latitude: -10,
longitude: -10
},
{
latitude: -9,
longitude: -9
}
];
const stringLocations: string[] = locations.map((val: GeoPoint) =>
`${val.latitude},${val.longitude}`
);
expect(stringLocations).to.contain('-9.5,-9.5');
expect(stringLocations).to.contain('9.5,9.5');
I loved the suggestion from #sebastien-horin
But another way with Should syntax (for the specific property):
const data = [
{ _id: 5, title: 'Blah', owner: 'Ted', description: 'something' },
{ _id: 7, title: 'Test', owner: 'Ted', description: 'something' },
];
data.map((e) => e.title).every((title) => title.should.equal('Blah'));
An alternative solution could be extending the array object with a function to test if an object exists inside the array with the desired property matching the expected value, like this
/**
* #return {boolean}
*/
Array.prototype.HasObjectWithPropertyValue = function (key, value) {
for (var i = 0; i < this.length; i++) {
if (this[i][key] === value) return true;
}
return false;
};
(i put this in my main test.js file, so that all other nested tests can use the function)
Then you can use it in your tests like this
var result = query_result;
// in my case (using superagent request) here goes
// var result = res.body;
result.HasObjectWithPropertyValue('property', someValue).should.equal(true);

Get elements inside javascript object that shares similar property names

I want to know if there is a way to extract / search the elements which contain similar property from a javascript object.
Just to be more specific, If I have the following object:
Live Demo: http://jsfiddle.net/oscarj24/sMWUL/
var enrolled = {};
enrolled['enrolled/ruby/S1234'] = {
course: {
id: 'P01',
desc: 'Ruby course'
},
student: {
id: 'S1234',
name: 'John Doe'
}
};
enrolled['enrolled/php/S1234'] = {
course: {
id: 'P02',
desc: 'PHP course'
},
student: {
id: 'S1234',
name: 'Foo Bar'
}
};
enrolled['enrolled/java/S6666'] = {
course: {
id: 'P03',
desc: 'Java course'
},
student: {
id: 'S6666',
name: 'Bill Gates'
}
};
Then I'll have some similar properties inside the enrolled object (like the ones sharing the S1234 string at the end).
So, my question is:
How can I extract the elements with string similarities or coincidences in the properties?
I've looked that javascript objects are very limited and the only thing I can do to check if a property exists or not is: obj.hasOwnProperty(prop) (but this is not what I am looking for). Is there a way to use regex to check for this? (just saying, seems not to be possible).
Just to know, I am using ExtJS 4.2 but I can't find something to achieve what I need in the API documentation (correct me if wrong).
You can use a for each loop to see if what you're searching for is in the string.`
for (key in enrolled)
{
if(key.indexOf('S1234') > -1)
{
console.log(key);
//Perform your actions here
}
}
Fiddle here: http://jsfiddle.net/brettwlutz/sMWUL/2/
how about this?
for(var prop in enrolled){
console.log(prop);
//check if prop matches string regex.
}

Categories