Node not logging deeper subobject - javascript

This may have been answered, but I did search.
In js file:
console.log({
a: 1,
b: { c: 1},
d: [{e:1},{f:1}],
g: [{h:[1,2,3]}]
});
This is what actually prints:
{ a: 1,
b: { c: 1 },
d: [ { e: 1 }, { f: 1 } ],
g: [ { h: [Object] } ]
}
Notice 'h' value, can I print this?

Read the docs for util.inspect()
It allows you to specify the depth to print at:
The default is to only recurse twice. To make it recurse indefinitely, pass in null for depth.
To use it, you could call console.log(util.inspect(yourObj, true, null));
console.dir() says it uses util.inspect(), but doesn't show parameters to modify the inspect() call, so it would probably only recurse twice, too.

You can use for loop to iterate over it..
var obj = {
a: 1,
b: {c: 1},
d: [{e: 1}, { f: 1}],
g: [{ h: [1, 2, 3]}]
};
var data = obj.g[0].h ;
for(var i =0; i <data.length ; i++){
console.log(data[i])
}​
Check Fiddle

I have used JSON.stringify() to achieve it, you can use parameters to determine the formatting.
As written above, util.inspect() also works.

Related

Jest failing one function but not another

I am writing some daily challenges for my coding bootcamp and I am running into an issue on one problem. I wrote a function that combines objects and it works correctly. Here is what the problem prompt is
Prompt: Write a function named mergeObjects that accepts at least two objects as arguments, merges the properties of the second through n objects into the first object, then finally returns the first object. If any objects have the same property key, values from the object(s) later in the arguments list should overwrite earlier values.
Examples:
mergeObjects({}, {a: 1}); //=> {a: 1} (same object as first arg)
mergeObjects({a: 1, b: 2, c: 3}, {d: 4}); //=> {a: 1, b: 2, c: 3, d: 4}
mergeObjects({a: 1, b: 2, c: 3}, {d: 4}, {b: 22, d: 44}); //=> {a: 1, b: 22, c: 3, d: 44
My function
function mergeObjects(...obj) {
let obj1 = {}
obj.forEach(element => {
obj1 = {...obj1, ...element}
});
return obj1
}
Solution function
function mergeObjects1(target, ...objects) {
objects.forEach(function (obj) {
// using ES2015's 'for in' loop
for (var key in obj) {
target[key] = obj[key]
}
})
return target
}
In my eyes these two functions provide the same result. However, when I run my code through the jest test they created it fails on the first test. But the solution they provide, does not fail. The jest test is below.
describe('15-mergeObjects', function () {
it('returns same object', function () {
var obj = {}
expect(mergeObjects(obj, { a: 1 })).toBe(obj)
})
it('adds additional properties', function () {
expect(mergeObjects({ a: 1, b: 2, c: 3 }, { d: 4 })).toEqual({
a: 1,
b: 2,
c: 3,
d: 4
})
})
it('merges props from left to right', function () {
expect(
mergeObjects({ a: 1, b: 2, c: 3 }, { d: 4 }, { b: 22, d: 44 })
).toEqual({ a: 1, b: 22, c: 3, d: 44 })
})
})
describe('15-mergeObjects', function () {
it('returns same object', function () {
var obj = {}
expect(mergeObjects1(obj, { a: 1 })).toBe(obj)
})
it('adds additional properties', function () {
expect(mergeObjects1({ a: 1, b: 2, c: 3 }, { d: 4 })).toEqual({
a: 1,
b: 2,
c: 3,
d: 4
})
})
it('merges props from left to right', function () {
expect(
mergeObjects1({ a: 1, b: 2, c: 3 }, { d: 4 }, { b: 22, d: 44 })
).toEqual({ a: 1, b: 22, c: 3, d: 44 })
})
})
Can anyone provide an explanation as to why the solution function passes while my function does not?
While the results look the same, the two functions are slightly different.
In your function, you are creating a new object and then adding to it all of the required properties.
In the solution function, they are adding properties to the original target object and then returning it.
The returned objects from both functions will have the same keys and the same values, but different references, so they are not considered the same object in JavaScript.
In the test
expect(mergeObjects1(obj, { a: 1 })).toBe(obj)
.toBe() checks whether two objects are the same (identity), therefore it fails the case of your function.
Note that there is a different test, .toEqual(), which checks whether two objects have the same keys and the same values (but possibly different references). Your function would pass this test
expect(mergeObjects1(obj, { a: 1 })).toEqual(obj)

Debugging Limitation Of Object Properties In Windows CMD

I am debugging Node.js script on windows command prompt with 'node inspect app.js'. The problem is when I use repl or exec('someObject') everytime I see only 5 properties even if the object has more than 5 properties. Is it some configuration which I should change or ?
This is what I see every time on this or other object which I want to inspect in cmd.
For example:
files.fileImg
{ domain: null,
_events: Object,
_eventsCount: 0,
_maxListeners: 'undefined',
size: 34814,
... } -> ***here there is more properties which are not shown***
Probably more of a workaround than an answer, but you could always do either (depending on your object's structure, circular references etc):
debug> exec('console.log(x)')
< { a: 1, b: 2, c: 3, d: 4, e: 5, f: 6 }
or
debug> exec('JSON.stringify(x)')
< { a: 1, b: 2, c: 3, d: 4, e: 5, f: 6 }
or
debug> exec('require("util").inspect(x, {depth: null})')
'{ a: 1, b: 2, c: 3, d: 4, e: 5, f: 6 }'
or any of the other one-line ways of dumping an object's contents.

Assign an object property value to another property while declaring the object

I have the following Javascript code:
var container = {
first: {
a: 1,
b: 'someString'
},
second: Object.assign({
c: 34,
d: 'something else'
},
this.first
)
}
console.log(container)
This prints:
{ first: { a: 1, b: 'someString' },
second: { c: 34, d: 'something else' } }
However, I would like it to be:
{ first: { a: 1, b: 'someString' },
second: { c: 34, d: 'something else', a: 1, b: 'someString'} }
So I would like all the (key, value) pairs from first to also be present in second. How can that be done?
You can't refer to an object before it exists, which is what you're trying to do. But you can do this:
var first = {
a: 1,
b: 'someString'
};
var container = {
first: first,
second: Object.assign({
c: 34,
d: 'something else'
},
first
)
}
console.log(container)
Problem:
In fact you are assigning the content of second with undefined, because at the time you are trying to refer the first property, at the assignement time, it doesn't exist yet in your container object.
Solution:
You need either to store the content of first property in an object before the assignement or create your container object with only first property and then define container.second property to get first value combined with second value.
This is how can be your code:
var container = {
first: {
a: 1,
b: 'someString'
}
};
container.second = Object.assign({
c: 34,
d: 'something else'
},
container.first
);
console.log(container)
You may looking for this.
var a = new function(){
this.b = {name:"Vignesh",place:"India"};
this.c = {name:"Vijay",place:"TamilNadu",b:this.b};
this.d = {name:"Vijay Sethupathi",place:"Namakkal",c:this.c};
}();
console.log(a);
var container = {
first: {
a: 1,
b: 'someString'
}
}
container.second = Object.assign(
{
c: 34,
d: 'Something else'
},
container.first
)

Chai expect: an array to contain an object with at least these properties and values

I'm trying to validate that an array of objects like this:
[
{
a: 1,
b: 2,
c: 3
},
{
a: 4,
b: 5,
c: 6
},
...
]
contains at least one object with both { a: 1 } and { c: 3 }:
I thought I could do this with chai-things, but I don't know all the properties of the object to be able to use
expect(array).to.include.something.that.deep.equals({ ??, a: 1, c: 3});
and contain.a.thing.with.property doesn't work with multiple properties :/
What's the best way to test something like this?
The desired solution seems to be something like:
expect(array).to.include.something.that.includes({a: 1, c: 3});
I.e. array contains an item which includes those properties. Unfortunately, it appears to not be supported by chai-things at the moment. For the foreseeable future.
After a number of different attempts, I've found that converting the original array makes the task easier. This should work without additional libraries:
// Get items that interest us/remove items that don't.
const simplifiedArray = array.map(x => ({a: x.a, c: x.c}));
// Now we can do a simple comparison.
expect(simplifiedArray).to.deep.include({a: 1, c: 3});
This also allows you to check for several objects at the same time (my use case).
expect(simplifiedArray).to.include.deep.members([{
a: 1,
c: 3
}, {
a: 3,
c: 5
}]);
Most elegant solution I could come up with (with the help of lodash):
expect(_.some(array, { 'a': 1, 'c': 3 })).to.be.true;
Most straight forward way I can think of is:
const chai = require('chai');
const expect = chai.expect;
chai.use(require('chai-like'));
chai.use(require('chai-things'));
expect([
{
a: 1,
b: 2,
c: 3,
},
{
a: 4,
b: 5,
c: 6,
},
]).to.be.an('array').that.contains.something.like({ a: 1, c: 3 });
Seems like the chai-subset plugin from chai seems to have done the trick. Here is something I have working:
const chai = require('chai');
const chaiSubset = require('chai-subset');
chai.use(chaiSubset);
const expect = chai.expect;
expect([ { type: 'text',
id: 'name',
name: 'name',
placeholder: 'John Smith',
required: 'required' },
{ type: 'email',
id: 'email',
name: 'email',
placeholder: 'example#gmail.com',
required: 'required' },
{ type: 'submit' } ]).containSubset([{ type: 'text', type: 'email', type: 'submit' }]);
Solution without third libraries or plugins:
let array = [
{ a: 1, b: 2, c: 3 },
{ a: 4, b: 5, c: 6 }
];
let match = array.map(({a, c}) => ({a, c})).to.deep.include({ a:1, c:3});
You could write your own function to test the array. In this example you pass in the array and the object containing the relevant key/value pairs:
function deepContains(arr, search) {
// first grab the keys from the search object
// we'll use the length later to check to see if we can
// break out of the loop
var searchKeys = Object.keys(search);
// loop over the array, setting our check variable to 0
for (var check = 0, i = 0; i < arr.length; i++) {
var el = arr[i], keys = Object.keys(el);
// loop over each array object's keys
for (var ii = 0; ii < keys.length; ii++) {
var key = keys[ii];
// if there is a corresponding key/value pair in the
// search object increment the check variable
if (search[key] && search[key] === el[key]) check++;
}
// if we have found an object that contains a match
// for the search object return from the function, otherwise
// iterate again
if (check === searchKeys.length) return true;
}
return false;
}
deepContains(data, { a: 4, c: 6 }); // true
deepContains(data, { a: 1, c: 6 }); // false
DEMO

Ramda does not provide deep mixin?

var _ = require('ramda');
var obj1 = {
innerNum: 1,
innerObj: {
innerStr: 'a',
innerStrB: 'Z'
}
};
var obj2 = {
innerNum: 2,
innerObj: {
innerStr: 'b'
}
};
var mixedObj = _.mixin(obj1, obj2);
mixedIObj does not include the inner object's innerStrB.
Any ramda solution?
It's not clear what you would want here. Most mixin/extend implementations I've seen are shallow, adding the values of the keys in the second object to those of the first, overriding where the keys are duplicated.
Ramda does have functions to clone an object with an updated value at a particular path: assocPath. I'm guessing that this wouldn't do everything you seem to want, though:
R.assocPath('innerObj.innerStr', 'b', obj1); //=>
// {
// innerNum: 1,
// innerObj: {
// innerStr: 'b',
// innerStrB: 'Z'
// }
// }
The question is what a deep mixin would really mean. If the objects have the same structure, it's pretty clear, but if they don't, it might be a little hairy:
mixinDeep(
{a: 1, b: {c: 2, d: 3}},
{b: {d: {e: 4, f: 5}, g: 6}}
);
// ?=>? {a: 1, b: {c: 2, d: {e: 4, f: 5}, g: 6}}
If that's the sort of thing you're looking for, then the Ramda team would love to have an issue raised or even a pull request.

Categories

Resources