I use TypeScript.
I want to get only the value of an object, but this error occurs: “TypeError: Cannot read properties of undefined (reading 'cd1')”.
callList = {
cd1: "00001",
nm1: "17"
}
// cd = '17'
const getFindbyNm(cd) => {
const idx = callList.find(e => e.nm1 == cd)
console.log(idx['cd1']); // ← Error occuered.
}
What am I doing wrong?
Your code isn't properly structured, it's not really valid JS even.
With some code cleaning, it works, but as some have stated, you need to use an Array for .find() to work.
const callList = {
cd1: "00001",
nm1: "17"
};
const cd = '17';
const getFindbyNm = (param1, param2) => {
return param1.find(e => e.nm1 == param2);
};
console.log(getFindbyNm([callList], cd));
console.log(getFindbyNm([callList], cd).cd1);
Considering callList is an Array
const callList =
[{
cd1: "00001",
nm1: "17"
}]
Array.prototype.find returns an array item or undefined, as an item may not be found within the given array. This is why idx may be undefined, hence cd1 may not exist on undefined
To fix it you can either check if idx isn't undefined
if(idx){
console.log(idx['cd1']);
}
or use the optional chaining operator ?.
console.log(idx?.['cd1'])
TS Playground
you can use Object.entries instead of find since find is function in array not in object. Object.entries has the attributes of both the key and the value
const callList = {
cd1: "00001",
nm1: "17",
};
const getFindByNm = (cd) => {
let returnval;
Object.entries(callList).forEach(([key, value]) => {
if (key == 'nm1' && value == cd) {
returnval = value;
}
});
return returnval;
};
let val = getFindByNm("17");
console.log(val);
Related
I need to set all properties of some object to null.
But the object can be very big, so I can't just do it one by one.
How to set all properties at once?
Here's a useful function called 'Object.keys()', it returns all of the attribute names of an object.
let setAll = (obj, val) => Object.keys(obj).forEach(k => obj[k] = val);
let setNull = obj => setAll(obj, null);
Non-arrow-function version:
function setAll(obj, val) {
/* Duplicated with #Maksim Kalmykov
for(index in obj) if(obj.hasOwnProperty(index))
obj[index] = val;
*/
Object.keys(obj).forEach(function(index) {
obj[index] = val
});
}
function setNull(obj) {
setAll(obj, null);
}
If you are looking for a short one-liner to copy and paste, use this
Object.keys(obj).forEach((i) => obj[i] = null);
Another way of doing it, using Array.reduce. It does not overwriting the existing object. This only works if the object only have simple values.
const newObj = Object.keys(originalObj).reduce(
(accumulator, current) => {
accumulator[current] = null;
return accumulator
}, {});
You can use Object.keys() as Nianyi Wang mentioned in his answer, or a for in, like this:
for (key in obj) {
if (obj.hasOwnProperty(key)) {
obj[key] = null;
}
}
But in this case you should check hasOwnProperty().
But the object can be very big, so I can't just do it one by one.
By "big" do you mean "millions of properties" and you are concerned about performance? Or do you mean "a bunch of properties you don't know the names of, and/or don't want to have list out"?
How to set all properties at once?
You can't. One way or another, you have to loop.
Instead of mutating an existing object, consider creating a new, empty object. Its property values will be undefined, but that could work depending on your code structure.
Lodash can manage this using cloneDeepWith.
My solution to the same problem:
import * as _ from 'lodash';
const bigObj = {"big": true, "deep": {"nested": {"levels": "many" } } };
const blankObj = _.cloneDeepWith(bigObj, (value) => {return _.isObject(value) ? undefined : null});
console.log(blankObj);
// outputs { big: null, deep: { nested: { levels: null } } }
Returning undefined in the customizer was not obvious to me, but this answer explains that doing so triggers recursion.
If object contains child object, if you want to set all child object properties to null, recursive solution is below.
function setEmpty(input){
let keys = Object.keys(input);
for( let key of keys ){
if(typeof input[key] != "object" ){
input[key] = null;
}else{
setEmpty(input[key]);
}
}
return input;
}
you can use for in. Here is an example:
let obj = {prob1:"value1", prob2:"value2"}
for(let prob in obj){obj[prob]=null}
export const setObjToNull = (obj) => {
var returnObj = {};
Object.keys(obj).map((key) => {
let nullObj = { [key]: '' };
Object.assign(returnObj, nullObj);
})
return returnObj;
}
You can use Object.fromEntries & Object.entries like this
Object.fromEntries(
Object.keys(obj).map((key) => [key, null])
)
let values = {
a:1,
b:'',
c: {
a:'',
s:4,
d: {
q: '',
w: 8,
e: 9
}
}
}
values;
const completeWithNull = (current) => {
Object.keys(current).forEach((key) => {
current[key] = current[key] === ''? null
: typeof current[key] === 'object' ? completeWithNull(current[key])
: current[key]
});
return current;
};
completeWithNull(values);
I have object with several properties, says it's something like this
{ a: "", b: undefined }
in jsx is there any one line solution I can check whether that object's property is not empty or has value or not? If array there's a isEmpty method.
I tried this
const somethingKeyIsnotEmpty = Object.keys((props.something, key, val) => {
return val[key] !== '' || val[key] !== undefined
})
In lodash, you can use _.some
_.some(props.something, _.isEmpty)
You can use lodash _.every and check if _.values are _.isEmpty
const profile = {
name: 'John',
age: ''
};
const emptyProfile = _.values(profile).every(_.isEmpty);
console.log(emptyProfile); // returns false
Possible ways:
Iterate all the keys and check the value:
let obj = {a:0, b:2, c: undefined};
let isEmpty = false;
Object.keys(obj).forEach(key => {
if(obj[key] == undefined)
isEmpty = true;
})
console.log('isEmpty: ', isEmpty);
Use Array.prototype.some(), like this:
let obj = {a:0, b:1, c: undefined};
let isEmpty = Object.values(obj).some(el => el == undefined);
console.log('isEmpty: ', isEmpty);
Check the index of undefined and null:
let obj = {a:1, b:2, c: undefined};
let isEmpty = Object.values(obj).indexOf(undefined) >= 0;
console.log('isEmpty: ', isEmpty);
A simple and elegant solution to check if all property values in an object is empty or not is following,
const ageList = {
age1: 0,
age: null
};
const allAgesEmpty = _.values(ageList).every((age) => !age);
console.log(allAgesEmpty); // returns true
Regarding the function inside _.every
Note: Do not use _.empty inside every as empty of a number always return false.
Read more here: https://github.com/lodash/lodash/issues/496
Note: if a property has a boolean value then you may need to modify the function even more
const profile = {
name: 'John',
age: ''
};
const emptyProfile = .values(profile).every(.isEmpty);
This solution is more efficient to check if each key is really empty
I have an object which looks like that:
const myObject = {
3723723: null
,3434355: true
,9202002: null
}
Using jQuery grep method I need to get the count of the array where the value is not null.
const result = $.grep(myArray, function (k, v) { return v != null; });
const count = result.length;
The variable you're talking about is actually not an array, but an object.
You don't need jQuery to find the number of values which are not null. Call the Object.values() function to get the values of that object as an array, then use the filter() method to filter out values which are null and then check the length property.
const myObject = {
3723723: null
,3434355: true
,9202002: null
}
console.log(Object.values(myObject).filter(x => x !== null).length)
Alternative solution using Object.keys():
const myObject = {
3723723: null
,3434355: true
,9202002: null
}
console.log(Object.keys(myObject)
.map(x => myObject[x])
.filter(x => x !== null).length)
In JavaScript you can use objects to get data structure you want.
var data = {
3723723: null,
3434355: true,
9202002: null
}
And to count properties where the value isn't null you can use Object.keys() to get array of object keys and then reduce() to get count.
var data = {
3723723: null,
3434355: true,
9202002: null
}
var result = Object.keys(data).reduce(function(r, e) {
if(data[e] != null) r += 1;
return r;
}, 0);
console.log(result)
I'm trying to grab the classes array based an id from the object. (and store it)
const objs = {
"1":{
"name":"Candice",
"classes": [00029,00023,00032,000222],
"id":0002918
},
"2":{
"name":"Clark",
"classes":[000219,00029,00219],
"id":00032
}
}
const objsKeys = Object.keys(objs);
const userClasses = objKeys.find(a => objs[a].id === this.state.userId).classes
console.log(userClasses);
// expect output
[00029,00023,00032,000222]
// but returns
Uncaught TypeError: Cannot read property 'classes' of undefined
What am I doing wrong here? Thank you for your help in advance!
You are getting the property name using Array#find method, and you are trying to get classes property of string and which is undefined . So you need to get the property value from object using the property name returned by Array#find method.
const userClasses = objs[objKeys.find(a => objs[a].id === this.state.userId)].classes
You are only getting the key.
Try:
const objs = {
"1":{
"name":"Candice",
"classes": [00029,00023,00032,000222],
"id":0002918
},
"2":{
"name":"Clark",
"classes":[000219,00029,00219],
"id":00032
}
}
const objsKeys = Object.keys(objs);
//if you console.log the following, you get the property/key of 2:
console.log(objsKeys.find(a => objs[a].id === 00032))
// you need to use that property to get the object value
const userClasses = objs[objsKeys.find(a => objs[a].id === this.state.userId)].classes
console.log(userClasses);
ive got an object:
var car = {
company: "Honda",
year: "2011",
Model: "Brio"
}
I was wondering if there exists an inherited method (is that the right phrase?) to check if a value exists inside a given object, somewhat like x.hasOwnProperty, or if (x in car). Or, should I write my own.
I've done a few google searches, but they all either lead to hasOwnProperty or to check if a value exists inside an array.
Editing to please all the people in the comments:
There are two use cases i could think of where this would be useful:
checking for undefined keys and reporting which one
if (!car.isInvalid(car, undefined))
validCarsArray.push (car);
Checking if a general user input exists in an object
var text = searchBox.input;
validCarArrays.forEach (function (car) {
if (car.hasOwnValue(car, text)) {
displayToUserAsResult (car);
}
});
Let's say we start with
const obj = {foo : "bar"};
Check for a value:
const hasValue = Object.values(obj).includes("bar");
Check for a property:
// NOTE: Requires obj.toString() if key is a number
const hasProperty = Object.keys(obj).includes("foo");
Multi-level value:
function hasValueDeep(json, findValue) {
const values = Object.values(json);
let hasValue = values.includes(findValue);
values.forEach(function(value) {
if (typeof value === "object") {
hasValue = hasValue || hasValueDeep(value, findValue);
}
})
return hasValue;
}
Multi-level property:
function hasPropertyDeep(json, findProperty) {
const keys = Object.keys(json);
let hasProperty = keys.includes((findProperty).toString());
keys.forEach(function(key) {
const value = json[key];
if (typeof value === "object") {
hasProperty = hasProperty || hasPropertyDeep(value, findProperty);
}
})
return hasProperty;
}
No, there is no built in method to search for a value on an object.
The only way to do so is to iterate over all the keys of the object and check each value. Using techniques that would work even in old browsers, you can do this:
function findValue(o, value) {
for (var prop in o) {
if (o.hasOwnProperty(prop) && o[prop] === value) {
return prop;
}
}
return null;
}
findValue(car, "2011"); // will return "year"
findValue(car, "2012"); // will return null
Note: This will return the first property that contains the search value even though there could be more than one property that matched. At the cost of efficiency, you could return an array of all properties that contain the desired value.
Note: This uses the extra .hasOwnProperty() check as a safeguard against any code that adds enumerable properties to Object.prototype. If there is no such code and you're sure there never will be, then the .hasOwnProperty() check can be eliminated.
There is no built-in function but it can be done using Object.keys() and [].some():
function hasValue(obj, value) {
return Object.keys(obj).some((key) => obj[key] == value);
}
var car = {
company: "Honda",
year: "2011",
Model: "Brio"
}
snippet.log('car has Honda: ' + hasValue(car, 'Honda'));
snippet.log('car has NotHonda: ' + hasValue(car, 'NotHonda'));
<script src="https://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
This function uses Object.keys() and returns an array with the keys for the object which has the given value.
The Object.keys() method returns an array of a given object's own enumerable properties, in the same order as that provided by a for ... in loop (the difference being that a for-in loop enumerates properties in the prototype chain as well).
var car = {
company: "Honda",
year: "2011",
Model: "Brio"
};
function getKeysWithValue(v, o) {
return Object.keys(o).filter(function (k) {
return o[k] === v;
});
}
document.write('<pre>' + JSON.stringify(getKeysWithValue('Honda', car), 0, 4) + '</pre>');
I used this function, to check wether or not array2 contains a common value with array1.
const array1 = ['a','b','c','x'];
const array2 = ['z','y','x'];
function ContainsCommonItem3(arr1, arr2){
return arr1.some(item => arr2.includes(item));
}