Getting an object by its name contained in a string - javascript

I am trying to get a const object indirectly by its name, which is contained in a string. I have no idea if this is possible but if it is, it would make my life a hell of a lot easier. As an example in pseudocode: var obj = findObject("myConstObject");
I know this is a strange thing to need, but I am dealing with quite a large amount of data, and being able to grab objects in this way would work a lot better with my existing code. Thanks in advance!

You can use Object.getOwnPropertyNames() to get all property names of an object. Here is an example that demonstrates how to search a myObj1 that is in the global window scope, and a myObj2 that is in the myStuff object scope:
// object attached to window object:
myObj1 = { a: 1 };
function getKeyNames(aThis) {
return Object.getOwnPropertyNames(aThis || globalThis).sort();
}
console.log('search myObj1 in global scope:', getKeyNames().filter(name => name === 'myObj1'));
// object attached to my on stuff:
const myStuff = {
myObj2: { b: 2 },
deeperLevel: {
myObj3: { b: 3 },
}
}
console.log('search myObj2 in myStuff scope:', getKeyNames(myStuff).filter(name => name === 'myObj2'));
Output:
search myObj1 in global scope: [
"myObj1"
]
search myObj2 in myStuff scope: [
"myObj2"
]
Notes:
if needed, expand this code to search recursively the object hierarchy, so that myStuff.deeperLevel.myObj3 can be found searching myStuff
if needed, expand this code to search a list of objects of interest

Related

How to grab the children of an Object.keys(myEl) reference

In the code below, I can get a reference to the text000 object, but I need to capture its child array as my target payload. Once I have a reference to the key, how can I capture its children?
Full object is below:
activeItem = [{"dnd":{"index":0,"active":true,"group":"common","label":"Text (000)","type":"text"},
"json":{"schema":{"properties":{"text000":{"title":"Text (000)","type":"string"}},"required":["text000"]},"layout":[{"key":"text000","description":"","floatLabel":"auto","validationMessages":{"required":"Required"}}]}}]
To grab a reference to the "text000" key I'm using:
const myEl = Object.keys(this.activeItem.json.schema.properties); // points to text000
I need to pull that key's contents/children > {"title":"Text (000)","type":"string"} out to use it as my target payload for this operation.
The text000 element is dynamic so I need its reference, which is why I'm using the Object.keys() method to point to it.
Feel free to school me on the proper names to use to refer to these elements. For example, not sure exactly how to reference > {"title":"Text (000)","type":"string"} with respect to the key text000. Is that the key's "children", "value", "contents" or what?
UPDATE:
console.log('TRY: ', this.activeItem.json.schema.properties[0]);
// Returns undefined
console.log('TRY2: ', this.activeItem.json.schema.properties);
// Returns {"text000":{"title":"Text (000)","type":"string"}}
I need something to return:
{"title":"Text (000)","type":"string"}
SOLUTION thanks #jaredgorski:
const properties = this.activeItem.json.schema.properties;
const propertiesKeys = Object.keys(properties);
const propertiesKeysFirstVal = Object.keys(properties)[0];
const logProperties = properties[propertiesKeysFirstVal];
console.log('PROPERTIES KEYS:', propertiesKeys);
console.log(
'VALUES OF FIRST PROPERTIES KEY:',
propertiesKeysFirstVal
);
console.log('RESULT:', logProperties);
PROPERTIES KEYS: ["text000"]
wrux-wrux-form-builder.js:1782 VALUES OF FIRST PROPERTIES KEY: text000
wrux-wrux-form-builder.js:1783 RESULT: {title: "Text (000)", type: "string"}
You need to remember that activeItem is an array. As long as you include the index (in this case the first index, which is [0]), you can access the json property (or key) and continue down the chain to retrieve the values in text000.
The other trick here is that you're wanting to access the first key in properties, but you don't know the name of that key yet. So what you need to do is actually make an array of the keys and then find out the name of the first key in that properties object. To do this, you can use Object.keys(), a method which turns the keys of an object into an array. Once you have the name of this key, you only need to use bracket notation on the properties object to find the value for this key. I'll show you how this works in the snippet below.
Here are some references so that you can learn more about how this works:
MDN page on the Object.keys() method
Accessing JavaScript
object properties: Bracket notation vs. Dot notation
And here's the working example:
const activeItem = [
{
"dnd": {
"index": 0,
"active": true,
"group":"common",
"label":"Text (000)",
"type":"text",
"icon":"text_fields",
"fontSet":"material-icons",
"class":""
},
"json": {
"schema": {
"properties": {
"text000":{
"title":"Text (000)",
"type":"string"
}
},
"required":["text000"]
},
"layout":[
{
"key":"text000",
"description":"",
"floatLabel":"auto",
"validationMessages": {
"required":"Required"
}
}
]
}
}
]
// This is the dirty looking version:
const logPropertiesDirty = activeItem[0].json.schema.properties[Object.keys(activeItem[0].json.schema.properties)[0]]
console.log("First, the dirty version where we don't save anything to variables. Everything is laid out here.")
console.log('WHAT WE DID:', 'activeItem[0].json.schema.properties[Object.keys(activeItem[0].json.schema.properties)[0]]')
console.log('RESULT:', logPropertiesDirty)
console.log('=================================================')
// This is the cleaner version, using variables to store things as we go:
const properties = activeItem[0].json.schema.properties;
const propertiesKeys = Object.keys(properties);
const propertiesKeysFirstVal = Object.keys(properties)[0];
const logPropertiesClean = properties[propertiesKeysFirstVal];
console.log('Now, the cleaner version. We save some values to variables to make things more readable.')
console.log('PROPERTIES OBJECT:', properties)
console.log('PROPERTIES KEYS:', propertiesKeys)
console.log('NAME OF FIRST PROPERTIES KEY:', propertiesKeysFirstVal)
console.log('RESULT:', logPropertiesClean)
Regarding what to call these things, I've always thought of Objects as generally consisting of "key-value pairs". Keys can also be called properties and values can also be called contents (I guess).
myObject = {
key1: value1,
property2: contentsOfProperty2
}
At the end of the day, clear communication is all that counts! So, whatever names you come up with (as long as they make reasonable sense), I'm sure people won't be jerks about it unless they feel like they have something to prove.
You should be able to use Object.values over this.activeItem.json.schema.properties:
The Object.values() method returns an array of a given object's own enumerable property values, 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).
const object1 = {
a: 'somestring',
b: 42,
c: false
};
console.log(Object.values(object1));
// expected output: Array ["somestring", 42, false]
It is not supported across the map yet, but you should be able to load a polyfill if you need it.

What is array besides string/arrays?

Trying to learn javascript by reading underscore sourcecode and came across the below code:
var shallowProperty = function(key) {
return function(obj) {
return obj == null ? void 0 : obj[key];
};
};
var getLength = shallowProperty('length');
console.log(getLength('123'))//3
console.log('123'['length'])//3
console.log(getLength(['1','2']))//2
console.log(['1','2']['length'])//2
My question is, what is [length] besides ['1','2']? Any technical terms to call it? Where can we get the full list of keys/attributes available other than length?
An array is a JavaScript object. An object can have properties. You can access them in a few, equivalent ways:
myObject.property
myObject['property']
See this MDN documentation.
To show all the properties of an object:
Object.getOwnPropertyNames(myObject);
You might like to refer to this question about listing the properties of an object.
Suppose you have the following object:
let person = {
name: 'foo',
age: 23
}
// Then, there are two possible ways to get the properties of "person" object
console.log(person.name); // logs 'foo'
console.log(person['name']); // logs 'foo'

Javascript objects and arrays references behaving different deppending on the depth

Just trying to understand why this is happening.
I was experimenting a bit with javascript arrays, objects and references to the objects. Then I reached a point where I don't understand anymore.
I create an array that holds an object; then when I do a reference to that object and change a property; the values of the original and the reference are changed automatically. Obviously because it's a reference and not a copy.
I was expecting the same when I create an array with an object that holds and array with one other object but somehow in that case the original object remains untouched.
Probably It has a really simple explanation that I don't know right now. Someone could explain me that?
Thanks!
var foo = [
{
"bar": "bar"
}
];
var ref = foo[0];
ref.bar = "new bar";
console.info(foo[0].bar); // output: new bar
console.info(ref.bar); // output: new bar
console.info(foo[0].bar === ref.bar); // output: true
var foo2 = [
{
"bar2": [
{ "nested": "nested" }
]
}
];
var ref2 = foo2[0].bar2;
ref2.nested = "nested 2";
console.info(foo2[0].bar2[0].nested); // output: nested
console.info(ref2.nested); // output: nested 2
console.info(foo2[0].bar2[0].nested === ref2.nested); // output: false
Everything is going fine. Nothing has changed. you understood well.
It's just that you put foo2[0].bar2 in var ref2.
var ref2 = foo2[0].bar2;
you see foo2[0].bar2 is an array here. when you did
*ref2.nested = "nested 2";*
It added a new object to ref2.
what you want to do is
*var ref2 = foo2[0].bar2[0];*
Or anything else subtle.
Javascript is same friend. It's just us who lose reference.

JavaScript: Stringify actual variable name

I'm currently running a series of functions where the first argument is a variable defined elsewhere, and the second argument is a string that happens to be identical to the variable name:
assignString(Hello, 'Hello')
assignString(World, 'World')
assignString(Foo, 'Foo')
assignString(Bar, 'Bar')
...
Ideally I would like to simplify this to something like this:
['Hello', 'World', 'Foo', 'Bar'].forEach(() => { assignString... })
or
[Hello, World, Foo, Bar].forEach(() => { assignString... })
Is this actually possible?
const vars = { Hello, World, Foo, Bar };
Object.keys(vars).forEach(key => assignString(vars[key], key));
I think the only way you could dynamically create variables based on a string value is by doing something like this:
var exampleStringValue = 'HELLO';
window[exampleStringValue] = exampleStringValue;
console.log(window.HELLO);
// or, since window is the global context in the browser
console.log(HELLO)
I honestly can't say I can dream up a use-case where that's a good practice, but I don't know your use-case, so no judgement here :)
I'd also like to point out this little library that I've found useful for creating objects where the keys have same value as the name of the key: https://github.com/STRML/keyMirror. I've found that to be used pretty heavily in the React community.
Since the variable name and the string are equivalent, there's no need to pass it in twice. I'd rather pass in the scope of the variable. You could do this so it works in whatever scope you're in:
function assignString(scope, val){
scope[val] = val;
}
Called like
assignString(window, "Hello");
Output of console.log(Hello) ==> "Hello"
Using the new ES6 Map object, we can create name/value pairs in a structure that can then be turned into an Array, so forEach can work:
// Variables that assignString will need:
var Hello = "var1", World = "var2", Foo = "var3", Bar = "var4";
// Map object that contains name of variables and strings that match variable name
var m = new Map([[Hello, "Hello"],[World,"World"],[Foo, "Foo"], [Bar, "Bar"]]);
// Turn Map into Array so forEach will work:
var a = Array.from(m);
// Call forEach which calls assingString and passes key name
// (variable name) and string value
a.forEach((value) => { assignString(value[0], value[1]); });
See this fiddle: https://jsfiddle.net/qnwsajes/34/
You can create an object with your data, iterate over the keys, and pass the key-value-pair to your assignString function.
var data = {
Hello: Hello,
World: World,
Foo: Foo,
Bar: Bar
}
Object.keys(data).forEach(key => assignString(data[key], key));

Deleting JS Object Properties a few levels deep

I have an object like this:
var myObj = {
first: {
sub: {
level: "some text",
level2: "some more text"
},
sub2: {
level3: "Something"
}
},
second: {
stuff: "More stuff...lots of stuff"
}
}
what I want to be able to do is say
delete myObj.first.sub.level
But I won't know what is being passed, or how many levels deep I need to go in order to remove the correct property, meaning it could simply be:
Storage.removeItem('myObj.first'); // This is currently working
Or something more complex:
Storage.removeItem('myObj.first.sub2.level3'); // This doesn't work because I'm more than 1 level into the object.
I'm kind of stuck, because I can get to the point where I have the key "level3" and it's property "Something", but I can't figure out how to back-step correctly in order to delete the full section of that object.
I need to replicate it's place in myObj so I can delete the full passed object.
'myObj.first.sub.level3'
If that makes sense...
It's not pretty, but you could use something like this:
function deepDelete(target, context) {
// Assume global scope if none provided.
context = context || window;
var targets = target.split('.');
if (targets.length > 1)
deepDelete(targets.slice(1).join('.'), context[targets[0]]);
else
delete context[target];
}
deepDelete('first.sub.level3', myObj);
deepDelete('myObj.first.sub2.level3');
It would probably be a good idea to modify it to test for typeof context[targets[0]] !== 'undefined' before descending. How exactly you react to that (return false, throw, or whatever else) would depend on how you're using it.

Categories

Resources