How can i remove a field from an object - javascript

I have an array of object. For doing one opetation I need to remove few fields from this object and for some other operation I have to use the whole fields
But both of the array removing "regex" field. What is the mistake I am doing here?
var newob = {};
var myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
newob = JSON.stringify(myObject);
delete newob.regex;
console.log("Test1", newob);
console.log("Test2", myObject);

You're missing JSON.parse so you can create the object back. Otherwise, you're trying to delete a property regex of a string, which doesn't exist.
newob = JSON.parse(JSON.stringify(myObject));
JSON.stringify creates a string, you need to do JSON.parse to create an object from a JSON string.
For that object, you can use Object.assign({}, myObject) since it's a shallow clone.
newob = Object.assign({}, myObject);
// newobj = { ...myObject } // this will also work

The problem is that newObj is not a copy of myObject but a reference to it. Thus when you delete the filed of myObject you also see the change in newObj
To explain what I have said, look at this snippet:
> const a = {a: 1}
undefined
> b = a
{ a: 1 }
> a.c = 58
58
> b
{ a: 1, c: 58 }
You can copy the object like this:
const newobj = JSON.parse(JSON.stringify(myObject));
then changes on myObject won't affect newobj
There is an other problem:
newob = JSON.stringify(myObject);
is wrong here because you assign you want an object but JSON.stringify returns a string

If I understand you correctly you want to map the input data and remove the regex from each of the objects in your input array.
const items = [
{
ircEvent: 'PRIVMSG',
method: 'newURI',
regex: '^http://.*',
},
{
ircEvent: 'TEST',
method: 'newURI',
regex: '^http://.*',
},
]
const newItems = items.map(({ regex, ...item }) => item)
A good way to explain what is happening above is
const newArray = array.map(({dropAttr1, ...keepAttrs}) => keepAttrs)
But should you want to remove the key from one object only you could
const myObject = {
ircEvent: 'PRIVMSG',
method: 'newURI',
regex: '^http://.*',
}
const { regex, ...noRegex } = myObject
console.log(noRegex)
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment

Related

How to merge 2 Objects taken by input's val

I have two JSON objects and I want to merge them:
Object1: {"9":{"322":{"option0":"177"}}}
Object2: {"10":{"323":{"option":"456"}}}
And I want for final result to be like:
{
"9": {
"322": {
"option0": "177"
}
},
"10": {
"323": {
"option": "456"
}
}
}
I tried the concat method, but the result is this:
{
"9":{
"322":{
"option0":"177"
}
}
}
{
"10":{
"323":{
"option":"456"
}
}
}
PS: The objects are taken by input like so:
var object1 = $('input').val();
Use Object.assign()
const Array1 = {"9":{"322":{"option0":"177"}}}
const Array2 = {"10":{"323":{"option":"456"}}}
let newObject = Object.assign({}, Array1, Array2);
console.log(newObject);
ES6 way:
const object1 = {"9":{"322":{"option0":"177"}}}
const object2 = {"10":{"323":{"option":"456"}}}
const object3 = { ...object1, ...object2 }
console.log(object3)
Codepen:
https://codepen.io/anon/pen/eLxBdK?editors=0001
Use ES6 syntax whenever possible.
shorter code
more readable usually
this case in particular allows you to easily do deep merges (which was a pain before)
faster
Since you are getting the values from a text field, they will initially be JSON strings. In order to treat them like objects and merge then you need to parse them first. Then you can achieve your desired output using jQuery's $.extend() method, which merges one object into another.
Demo:
var obj1 = JSON.parse($("#obj1").val());
var obj2 = JSON.parse($("#obj2").val());
var merged= $.extend({}, obj1, obj2);
console.log(merged);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="obj1" value='{"9":{"322":{"option0":"177"}}}'/>
<input type="text" id="obj2" value='{"10":{"323":{"option":"456"}}}'/>
Documentation: https://api.jquery.com/jquery.extend/
Actually these are objects and not JSON Arrays, and you got an array as result because Array#concat() will return an array and what you want is an object.
So what you can do is to use Object.assign() method:
let obj = Object.assign({}, JSON.parse(o1), JSON.parse(o2));
Note:
If you take these objects from input, you will be getting them as strings you need to parse them with JSON.parse() to getb the right objects.
let o1 = '{"9":{"322":{"option0":"177"}}}';
let o2 = '{"10":{"323":{"option":"456"}}}';
let obj = Object.assign({}, JSON.parse(o1), JSON.parse(o2));
console.log(obj);

Is there a difference in Object.assign {} and Object.Assign []

I am going through some old code from a defunct developer and noticed that sometimes he used
Object.assign({}, xyz)
and others he used
Object.assign([], abc);
Is there a difference between the two?
Yes, there is a difference. One assigns the values to a new object and the other assigns the values to a new array.
Look at the output here and compare to the output in the actual browser console.
var abc = {foo:"bar"};
var r1 = Object.assign({},abc);
var r2 = Object.assign([],abc);
console.log(r1);
console.log(r2);
What the second one doesn't do is add a new item to the array - it still has a length of 0.
Object.assign is a function that copies the enumerable own properties from one object to another (called target) and returns the target object. Since arrays are also objects you can copy properties to them as well, however, they won't show up during iteration.
Take the following snippet for example:
obj is an object
arr is an object, but also an array
arr.a is 1
arr.forEach does not print a
const obj = Object.assign({}, {
a: 1,
0: 2
});
const arr = Object.assign([], {
a: 1,
0: 2
});
console.log(typeof obj);
console.log(typeof arr);
console.log(Array.isArray(arr));
console.log(obj);
console.log(arr);
console.log(Object.keys(arr));
console.log(arr.a);
arr.forEach((item, idx) => console.log(`${idx}: ${item}`));
// To test the question in the comments
let copiedObj = { a: 123 };
let copy = Object.assign({}, copiedObj);
console.log(copy);
copiedObj = [];
console.log(copiedObj);
console.log(copy);

Simplest way to copy JS object and filter out certain properties

If I have a JS object, and I'd like to create a new object which copies over all properties except for a blacklist of properties that need to be filtered out, what's the simplest way to do it?
So I would do something like
originalObject.copyAndFilter('a', 'b')
Which would take the original object, copy it, and make sure properties a and b aren't in the new object.
I'm using ES2015/2016 through Babel so if it provides an even simpler way that would work too.
You could use Set and delete the unwanted properties.
var object = { a: 1, b: 2, c: 3, d: 4 },
filteredObject = {},
p = new Set(Object.keys(object));
blacklist = ['a', 'b'];
blacklist.forEach(a => p.delete(a));
[...p].forEach(k => filteredObject[k] = object[k]);
console.log(filteredObject);
Well, there's no simple native way to do it, I would convert the keys to an array, filter it, then create a new object:
const obj = {a: 'foo', b: 'bar', c: 'baz'};
const blacklist = ['a', 'b'];
const keys = Object.keys(obj);
const filteredKeys = keys.filter(key => !blacklist.includes(key));
const filteredObj = filteredKeys.reduce((result, key) => {
result[key] = obj[key];
return result;
}, {});
console.log(filteredObj);
You can just loop over object keys and create a new object. You can even use for...in for it. This will have added advantage of being supported in all browsers.
var obj = {a: 'foo', b: 'bar', c: 'baz'};
var blackListKeys = ['a', 'b','z'];
var obj2 = {}
for(var k in obj){
if(blackListKeys.indexOf(k) === -1)
obj2[k] = obj[k];
}
console.log(obj2)
var obj = {foo: 1, a: 2, b:3}
var newObj = {}
var blacklist = ['a', 'b']
for(let [key, value] of Object.entries(obj)) {
!blacklist.includes(key) && (newObj[key] = value)
}
console.log(newObj)
With fewer variables:
var obj = {foo: 1, a: 2, b: 3}
var newObj = Object.entries(obj)
.filter(([key, val]) => !['a', 'b'].includes(key))
.reduce((newObj, [key, value]) => (newObj[key] = value, newObj), {})
console.log(newObj)
Here there are two problems:
First one is actually copying the object without references.
If you simply loop against object keys and perform assignments of its values from the original object, if that values are also objects, you end up referencing that objects (or even arrays), not copying itself. So you will need to detect that and recursively call your copy_object function to avoid references.
Fortunately that problem is already solved in some libraries which provides an object extend() function like npm (server side) and jQuery (browser).
The trick consist only on extending new freshly created object:
var dst_object = extend({}, src_object);
The second problem is to avoid undesired keys.
Here there are to possible approaches: One is to fully reimplement beforementioned extend() function in a way that they provide a blacklist functionality.
...and the second (and less error prone) is to simply drop undesired keys after copying the object. If they aren't huge data structures, the overhead will be insignificant.
Example:
// npm install --save extend
var extend = require("extend");
function oClone(target, blacklist) {
var dest = extend({}, target);
if (blacklist) {
for (var i=0; i<blacklist.length; i++) {
delete (dest[blacklist[i]]);
};
};
return dest;
};
I think Object.assign is the best ES5 utility to make this with little extra logic:
function copyAndFilter(...args){
var copy = Object.assign( {} , this);
args.forEach(prop => {
delete copy[prop];
}); return copy;
}
Then:
var a = {foo : 'foo' , bar : 'bar'};
a.copyAndFilter = /* function definition above*/
a.copyAndFilter('foo');// { bar : 'bar' }

Remove reference to another object in javascript

var b = {};
var a = b;
b.test = 123;
console.log(a.test);
I am trying to write code similar to the above, however for sake of not having to describe context I'll display that instead ^
After the line a = b I want to lose the reference from a to b, so I can update b without it affecting a, and vice-versa
Is this possible?
You can clone your object with Object.assign():
var a = Object.assign({}, b);
You can use JSON.stringify(obj) and then JSON.parse to the string.
So it'll be something like that:
let obj= {
hello: 'hello'
};
let string = JSON.stringify(obj);
let newObj = JSON.parse(string);
Or a shorter, one-line way:
let newObj = JSON.parse(JSON.stringify(obj))
Using Object.assign(), Object.create() or spread operator will not help you with arrays in objects (works with non-array properties though).
let template = {
array: []
};
let copy = { ...template };
console.log(template.array); // As expected, results in: []
copy.array.push(123);
console.log(template.array); // Output: [123]
But this can be solved using JSON.stringify() and JSON.parse(), as already said.
let template = {
array: []
};
let copy = JSON.parse(JSON.stringify(template));
console.log(template.array); // Output: []
copy.array.push(123);
console.log(template.array); // Output: []
Wonder if it is the most adequate solution...
Excuses if I'm missing something, am only a beginner.

Get array of object's keys

I would like to get the keys of a JavaScript object as an array, either in jQuery or pure JavaScript.
Is there a less verbose way than this?
var foo = { 'alpha' : 'puffin', 'beta' : 'beagle' };
var keys = [];
for (var key in foo) {
keys.push(key);
}
Use Object.keys:
var foo = {
'alpha': 'puffin',
'beta': 'beagle'
};
var keys = Object.keys(foo);
console.log(keys) // ['alpha', 'beta']
// (or maybe some other order, keys are unordered).
This is an ES5 feature. This means it works in all modern browsers but will not work in legacy browsers.
The ES5-shim has a implementation of Object.keys you can steal
You can use jQuery's $.map.
var foo = { 'alpha' : 'puffin', 'beta' : 'beagle' },
keys = $.map(foo, function(v, i){
return i;
});
Of course, Object.keys() is the best way to get an Object's keys. If it's not available in your environment, it can be trivially shimmed using code such as in your example (except you'd need to take into account your loop will iterate over all properties up the prototype chain, unlike Object.keys()'s behaviour).
However, your example code...
var foo = { 'alpha' : 'puffin', 'beta' : 'beagle' };
var keys = [];
for (var key in foo) {
keys.push(key);
}
jsFiddle.
...could be modified. You can do the assignment right in the variable part.
var foo = { 'alpha' : 'puffin', 'beta' : 'beagle' };
var keys = [], i = 0;
for (keys[i++] in foo) {}
jsFiddle.
Of course, this behaviour is different to what Object.keys() actually does (jsFiddle). You could simply use the shim on the MDN documentation.
In case you're here looking for something to list the keys of an n-depth nested object as a flat array:
const getObjectKeys = (obj, prefix = '') => {
return Object.entries(obj).reduce((collector, [key, val]) => {
const newKeys = [ ...collector, prefix ? `${prefix}.${key}` : key ]
if (Object.prototype.toString.call(val) === '[object Object]') {
const newPrefix = prefix ? `${prefix}.${key}` : key
const otherKeys = getObjectKeys(val, newPrefix)
return [ ...newKeys, ...otherKeys ]
}
return newKeys
}, [])
}
console.log(getObjectKeys({a: 1, b: 2, c: { d: 3, e: { f: 4 }}}))
I don't know about less verbose but I was inspired to coerce the following onto one line by the one-liner request, don't know how Pythonic it is though ;)
var keys = (function(o){var ks=[]; for(var k in o) ks.push(k); return ks})(foo);
Summary
For getting all of the keys of an Object you can use Object.keys(). Object.keys() takes an object as an argument and returns an array of all the keys.
Example:
const object = {
a: 'string1',
b: 42,
c: 34
};
const keys = Object.keys(object)
console.log(keys);
console.log(keys.length) // we can easily access the total amount of properties the object has
In the above example we store an array of keys in the keys const. We then can easily access the amount of properties on the object by checking the length of the keys array.
Getting the values with: Object.values()
The complementary function of Object.keys() is Object.values(). This function takes an object as an argument and returns an array of values. For example:
const object = {
a: 'random',
b: 22,
c: true
};
console.log(Object.values(object));
Year 2022 and JavaScript still does not have a sound way to work with hashes?
This issues a warning but works:
Object.prototype.keys = function() { return Object.keys(this) }
console.log("Keys of an object: ", { a:1, b:2 }.keys() )
// Keys of an object: Array [ "a", "b" ]
// WARN: Line 8:1: Object prototype is read only, properties should not be added no-extend-native
That said, Extending Built-in Objects is Controversial.
If you decide to use Underscore.js you better do
var foo = { 'alpha' : 'puffin', 'beta' : 'beagle' };
var keys = [];
_.each( foo, function( val, key ) {
keys.push(key);
});
console.log(keys);

Categories

Resources