Change default array-type getter Javascript - javascript

I found out that there is no way to do this. However, thanks everyone!
In javascript, can I override the brackets to access characters in a string?
I have something like this:
function f() {
var list = [{name: 'test'}, {name: 'test2'}];
}
And I would like to get properties from that list that's inside the function, I think there is some method that overrides default [], but I really don't know what to look for.
f[0] // {name: 'test'}
f['test2'] // {name: 'test2'}

Your list variable will be private to f() unless you do one of two things.
First, you could try returning list from f() so that you can then get to the properties you need.
function f() {
var list = [{name: 'test'}, {name: 'test2'}];
return list;
}
var f = f();
f[0] // {name: 'test'};
f['test'] // will return undefined; we'll come back to this
Second, and I think this option is probably what you're looking for as you tagged the question with 'oop', you could make f() a constructor:
function f() {
this.list = [{name: 'test'}, {name: 'test2'}];
}
var f1 = new f();
f1['list'][0] // {name: 'test'};
f1.list[0] // will also return {name: 'test'};
f1.list['test'] // still will return undefined...
...
The reason you will not be able to access a value using ['test'] or ['test2'] is because they are your values, whereas ordinarily the values are what we want to access in an object using the key (in this case ['name'] or .name). So what you might want is something like this:
f1.list[0].name // will return 'test'
f1.list[1].name // will return 'test2'
Hope this clears up the confusion.

Just use an object instead of an array:
var byname = {
"test": {name: 'test'},
"test2": {name: 'test2'}
};
// bracket notation:
byname["test2"] // {name: 'test2'}
// dot notation:
byname.test // {name: 'test'}
Since you said that you never will access the structure by index, it will be OK to use the unordered key-value-map structure. To save typing, you could create that object dynamically from your array as well:
var list = [{name: 'test'}, {name: 'test2'}];
var byname = {};
for (var i=0; i<list.length; i++)
byname[list[i].name] = list[i];

Related

generating list of objects using .filter() method javascript

I was studying up on the .filter() method in Javascript. I came across this example online.
var heroes = [
{name: "Batman", franchise: "DC"},
{name: "Ironman", franchise: "Marvel"},
{name: "Thor", franchise: "Marvel"},
{name: "Superman", franchise: "DC"}
];
var marvelHeroes = heroes.filter(function(hero) {
return hero.franchise == "Marvel";
})
document.write(marvelHeroes);
I expect to get an array of objects showing only the Marvel heroes. However, when I try to print the results of the marvelHeroes variable, I am getting the following result:
[object Object],[object Object]
Can someone tell me what is wrong here?
The issue is, you're sending it raw JavaScript objects. As others have pointed out, if you stringify this array, the error disappears. The reason that [object Object] shows up is that the browser can only put strings in HTML. So in order to coerce those objects into strings, it uses the Object#toString method, which results in each method being turned into a string as [object Object]. By using JSON.stringify to serialize the objects before writing it to the document, you ensure that the objects are properly represented in string form.
const object = { a: 'a', b: '2', c: 3 };
const stringOne = object.toString();
const stringTwo = JSON.stringify(object);
document.write(stringOne);
document.write(stringTwo);
You need to convert the JS data structure to a string to view it on the page. For that you use stringify. Further, to get a nice formatted output, and add the string to a pre element with a nice indentation.
var heroes = [{"name":"Batman","franchise":"DC"},{"name":"Ironman","franchise":"Marvel"},{"name":"Thor","franchise":"Marvel"},{"name":"Superman","franchise":"DC"}];
var marvelHeroes = heroes.filter(function(hero) {
return hero.franchise == "Marvel";
})
const pre = document.querySelector('pre');
pre.textContent = JSON.stringify(marvelHeroes, null, 2);
<pre></pre>
You try to write object, before that you need to stringify it (to json)
document.write(JSON.stringify(marvelHeroes));
var heroes = [
{name: "Batman", franchise: "DC"},
{name: "Ironman", franchise: "Marvel"},
{name: "Thor", franchise: "Marvel"},
{name: "Superman", franchise: "DC"}
];
var marvelHeroes = heroes.filter(function(hero) {
return hero.franchise == "Marvel";
})
document.write(JSON.stringify(marvelHeroes));

How does {...object, property: value} work with spread syntax?

When reviewing the ES6 docs, I noted that it is recommended to use the spread syntax over the more verbose Object.assign() method. But, I am a bit confused as to how this is being accomplished.
Is object in this case being broken down to key: value pairs, after which the property on the right of the comma is either added or overwritten, and finally being reassembled?
Is object in this case being broken down to key: value pairs, after which the property on the right of the comma is either added or overwritten, and finally being reassembled?
The key-value pairs of the original object object are actually being used in combination (merging) with the new object which has an extra property var2( they are getting combined to newObject).
You can think of it as object is becoming a subset of newObject in the place where the spread syntax in being used, while properties with same key are being overridden.
Check the below example:
const object = { txt: 'Test' };
const newObject = {...object, var2: 'aa' };
// logs Object {txt: "Test", var2: "aa"}
console.log(newObject);
const object2 = { txt: 'Test' };
const newObject2 = {...object, txt: 'Test2', var2: 'aa' };
// Object {txt: "Test2", var2: "aa"}
console.log(newObject2);
// merging all objects to a new object
var object3 = {first: 'Hello', second: 'World'};
var newObject3 = {...object, anotherVar: 'stack', ...object2, ...object3};
// Object {txt: "Test", anotherVar: "stack", first: "Hello", second: "World"}
console.log(newObject3);

With Underscore, how do I recursively flatten an array of objects?

I have a tree/traversable object that looks like this:
var data = {children: [
{
name: 'foo',
url: 'http://foo',
children: [
{
name: 'bar',
url: 'http://bar',
children: []
}
]
},
{
name: 'baz',
url: 'http://baz',
children: []
},
{
name: 'biff',
children: []
}
]};
What I need to do is be able to flatten the data into a single dimensional list:
var flattenedData = [{name: 'foo', url: 'http://foo'}, {name: 'bar', url: 'http://bar'}, {name: 'baz', url: 'http://baz'}, {name: 'biff'}];
Currently, I've created a recursive helper function to walk the data structure and push the results onto an array. I'd like to do this more functionally if possible. Something like:
var flattenedData = _.chain(data.children).flatten().filter(function(item){//real filtering; return item;}).value();
The problem is, flattening doesn't seem to flatten an array of objects, just simple arrays. I could be wrong.
How would I perform this task in a more functional way without traversing the tree in a helper function?
I don't see what you mean by "flatten doesn't seem to flatten an array of objects, just simple arrays" - how so? It most definitely can flatten any kind of array. Anyway, a simple one-pass solution using reduce:
Object.prototype.flatten = function () {
if (this instanceof Array) {
return this.reduce(function(a, b) {
return a.concat(b.flatten());
}, []);
}
var res = [];
// this is the example condition
if (this.url !== undefined) {
res.push(this);
}
return res.concat(this.children.flatten());
};
var flat_data = data.flatten();
print(flat_data);
By the way, it would be advisable to replace Object with your custom data type you want to flatten, so that you don't mess up the global prototype for all objects.

How to push an object in an Array?

Iam trying to push in array an object, but I get always error.
fCElements = [],
obj = {};
obj.fun = myFunction;
obj.id = 2;
fCElements.push ({
obj,
myid:2,
name:'klaus'
})
how I can push into array functions like "myFunction"?
Thanks
In the Object literal, you can only give key-value pairs. Your obj doesn't have any value.
Instead, you can do like this
var fCElements = [];
fCElements.push({
obj: {
fun: myFunction,
id: 2
},
myid: 2,
name: 'klaus'
});
Now, you are creating a new object, obj, on the fly, while pushing to the array. Now, your fCElements look like this
[ { obj: { fun: [Function], id: 2 }, myid: 2, name: 'klaus' } ]
You need to give your obj property a name (or a value).
var obj = {};
obj.fun = myFunction;
obj.id = 2;
fCElements.push ({
obj:obj,
myid:2,
name:'klaus'
});
The object you are pushing to the array seems off. It will try to push this object:
{
{fun: myfunction, id: 2},
myid: 2,
name: 'klaus'
}
Which is an invalid object since the first value has no key. You should do it like this instead:
fCElements.push ({
myObj:obj,
myid:2,
name:'klaus'
});

Combine or merge JSON on node.js without jQuery

I have multiple JSON like those
var object1 = {name: "John"};
var object2 = {location: "San Jose"};
They are not nesting or anything like that. Just basically different fields. I need to combine them into one single JSON in node.js like this:
{name: "John", location: "San Jose"}
I can use jQuery just fine. Here is a working example in the browser:
http://jsfiddle.net/qhoc/agp54/
But if I do this in node.js, I don't want to load jQuery (which is a bit over use, plus node.js' jQuery doesn't work on my Windows machine).
So is there a simple way to do things similar to $.extend() without jQuery?
You should use "Object.assign()"
There's no need to reinvent the wheel for such a simple use case of shallow merging.
The Object.assign() method is used to copy the values of all enumerable own properties from one or more source objects to a target object. It will return the target object.
var o1 = { a: 1 };
var o2 = { b: 2 };
var o3 = { c: 3 };
var obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1); // { a: 1, b: 2, c: 3 }, target object itself is changed
console.log(obj === o1) // true
Even the folks from Node.js say so:
_extend was never intended to be used outside of internal NodeJS modules. The community found and used it anyway.
It is deprecated and should not be used in new code. JavaScript comes with very similar built-in functionality through Object.assign.
Update:
You could use the spread operator
Since version 8.6, it's possible to natively use the spread operator in Node.js. Example below:
let o1 = { a: 1 };
let o2 = { b: 2 };
let obj = { ...o1, ...o2 }; // { a: 1, b: 2 }
Object.assign still works, though.
**PS1**: If you are actually interested in **deep merging** (in which internal object data -- in any depth -- is recursively merged), you can use packages like [deepmerge][4], [assign-deep][5] or [lodash.merge][6], which are pretty small and simple to use.
**PS2**: Keep in mind that **Object.assign doesn't work with 0.X versions of Node.js**. If you are working with one of those versions (_you really shouldn't by now_), you could use `require("util")._extend` as shown in the Node.js link above -- for more details, check [tobymackenzie's answer to this same question](https://stackoverflow.com/a/22286375/36272).
If using Node version >= 4, use Object.assign() (see Ricardo Nolde's answer).
If using Node 0.x, there is the built in util._extend:
var extend = require('util')._extend
var o = extend({}, {name: "John"});
extend(o, {location: "San Jose"});
It doesn't do a deep copy and only allows two arguments at a time, but is built in. I saw this mentioned on a question about cloning objects in node: https://stackoverflow.com/a/15040626.
If you're concerned about using a "private" method, you could always proxy it:
// myutil.js
exports.extend = require('util')._extend;
and replace it with your own implementation if it ever disappears. This is (approximately) their implementation:
exports.extend = function(origin, add) {
if (!add || (typeof add !== 'object' && add !== null)){
return origin;
}
var keys = Object.keys(add);
var i = keys.length;
while(i--){
origin[keys[i]] = add[keys[i]];
}
return origin;
};
Underscore's extend is the easiest and quickest way to achieve this, like James commented.
Here's an example using underscore:
var _ = require('underscore'), // npm install underscore to install
object1 = {name: "John"},
object2 = {location: "San Jose"};
var target = _.extend(object1, object2);
object 1 will get the properties of object2 and be returned and assigned to target.
You could do it like this as well, depending on whether you mind object1 being modified:
var target = {};
_.extend(target, object1, object2);
A normal loop?
function extend(target) {
var sources = [].slice.call(arguments, 1);
sources.forEach(function (source) {
for (var prop in source) {
target[prop] = source[prop];
}
});
return target;
}
var object3 = extend({}, object1, object2);
That's a basic starting point. You may want to add things like a hasOwnProperty check, or add some logic to handle the case where multiple source objects have a property with the same identifier.
Here's a working example.
Side note: what you are referring to as "JSON" are actually normal JavaScript objects. JSON is simply a text format that shares some syntax with JavaScript.
Use merge.
$ npm install merge
Sample code:
var merge = require('merge'), // npm install -g merge
original, cloned;
console.log(
merge({ one: 'hello' }, { two: 'world' })
); // {"one": "hello", "two": "world"}
original = { x: { y: 1 } };
cloned = merge(true, original);
cloned.x.y++;
console.log(original.x.y, cloned.x.y); // 1, 2
I see that this thread is too old, but I put my answer here just in logging purposes.
In one of the comments above you mentioned that you wanted to use
'express' in your project which has 'connect' library in the
dependency list. Actually 'connect.utils' library contains a 'merge'
method that does the trick. So you can use the 3rd party
implementation without adding any new 3rd party libraries.
Here is simple solution, to merge JSON.
I did the following.
Convert each of the JSON to strings using JSON.stringify(object).
Concatenate all the JSON strings using + operator.
Replace the pattern /}{/g with ","
Parse the result string back to JSON object
var object1 = {name: "John"};
var object2 = {location: "San Jose"};
var merged_object = JSON.parse((JSON.stringify(object1) + JSON.stringify(object2)).replace(/}{/g,","))
The resulting merged JSON will be
{name: "John", location: "San Jose"}
There is an easy way of doing it in Node.js
var object1 = {name: "John"};
var object2 = {location: "San Jose"};
To combine/extend this we can use ... operator in ECMA6
var object1 = {name: "John"};
var object2 = {location: "San Jose"};
var result = {
...object1,
...object2
}
console.log(result)
You can also use this lightweight npm package called absorb
It is 27 lines of code, 1kb and uses recursion to perform deep object merges.
var absorb = require('absorb');
var obj1, obj2;
obj1 = { foo: 123, bar: 456 };
obj2 = { bar: 123, key: 'value' }
absorb(obj1, obj2);
console.log(obj1); // Output: { foo: 123, bar: 123, key: 'value' }
You can also use it to make a clone or only transfer values if they don't exist in the source object, how to do this is detailed in the link provided.
It can easy be done using Object.assign() method -
var object1 = {name: "John"};
var object2 = {location: "San Jose"};
var object3 = Object.assign(object1,object2);
console.log(object3);
now object3 is { name: 'John', location: 'San Jose' }
Use spread operator. It is supported in Node since version 8.6
const object1 = {name: "John"};
const object2 = {location: "San Jose"};
const obj = {...object1, ...object2}
console.log(obj)
// {
// "name": "John",
// "location": "San Jose"
// }
If you need special behaviors like nested object extension or array replacement you can use Node.js's extendify.
var extendify = require('extendify');
_.extend = extendify({
inPlace: false,
arrays : 'replace',
isDeep: true
});
obj1 = {
a:{
arr: [1,2]
},
b: 4
};
obj2 = {
a:{
arr: [3]
}
};
res = _.extend(obj1,obj2);
console.log(JSON.stringify(res)); //{'a':{'arr':[3]},'b':4}
Lodash is a another powerful tool-belt option for these sorts of utilities. See: _.merge() (which is recursive)
var object = {
'a': [{ 'b': 2 }, { 'd': 4 }]
};
var other = {
'a': [{ 'c': 3 }, { 'e': 5 }]
};
_.merge(object, other);
// => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }
The below code will help you to merge two JSON object which has nested objects.
function mergeJSON(source1,source2){
/*
* Properties from the Souce1 object will be copied to Source2 Object.
* Note: This method will return a new merged object, Source1 and Source2 original values will not be replaced.
* */
var mergedJSON = Object.create(source2);// Copying Source2 to a new Object
for (var attrname in source1) {
if(mergedJSON.hasOwnProperty(attrname)) {
if ( source1[attrname]!=null && source1[attrname].constructor==Object ) {
/*
* Recursive call if the property is an object,
* Iterate the object and set all properties of the inner object.
*/
mergedJSON[attrname] = zrd3.utils.mergeJSON(source1[attrname], mergedJSON[attrname]);
}
} else {//else copy the property from source1
mergedJSON[attrname] = source1[attrname];
}
}
return mergedJSON;
}
You can use Lodash
const _ = require('lodash');
let firstObject = {'email' : 'email#email.com};
let secondObject = { 'name' : { 'first':message.firstName } };
_.merge(firstObject, secondObject)
A better approach from the correct solution here in order to not alter target:
function extend(){
let sources = [].slice.call(arguments, 0), result = {};
sources.forEach(function (source) {
for (let prop in source) {
result[prop] = source[prop];
}
});
return result;
}
You can do it inline, without changing any variables like this:
let obj1 = { name: 'John' };
let obj2 = { surname: 'Smith' };
let obj = Object.assign({}, obj1, obj2); // { name: 'John', surname: 'Smith' }
Let object1 and object2 be two JSON object.
var object1 = [{"name": "John"}];
var object2 = [{"location": "San Jose"}];
object1.push(object2);
This will simply append object2 in object1:
[{"name":"John"},{"location":"San Jose"}]

Categories