a few questions when iterator the arraylike object in javascript - javascript

In my application,I need to do some iteration with the array-like object.
So I write a custom util method:
Util.forEach=function(iterator,callback,context){
if(iterator.length){
for(var i=0;i<iterator.length;i++){
var val=iterator[i];
callback && callback.call(context||null,val,i);
}
}
}
Then I meet some problems:
Suppose I have an array: var ary=[1,2,3,4,5];
1. how to break the loop?
For example, if I want to find if value '2' is included in the array,I may try this:
Util.forEach(ary,function(value,index){
if(value==2){
//find mached value,now I should break and return this value.
//but I can not use 'break' in this context.
}
});
2. remove value of the array when iterator
If I want to remove value '2' of the array,I may try this:
Util.forEach(ary,function(value,index){
if(value==2){
//delete it.
ary.splice(i,1);
// I wonder if this is the safe way?
}
});
Since in java we can not do this when iterate an array,it will cause the concurrency exception.
Though I run the above code without any error,but I am not sure if it is the best practice?

Generally, you can break out from a forEach-like method by using try-catch and throw.
var value = 'Not Found';
try {
Util.forEach(ary, function(value, index) {
if(value == 2) {
throw value; //<-- Throw the found result: Terminates current forEach
}
});
} catch (found) { // Catch the thrown result
value = found;
}

The first issue can be solved by checking the return value from the callback and stopping the iteration if it returns false. Then you can stop the iteration by returning false from the callback. Returning anything other than false (including returning nothing) will continue the iteration. jQuery uses this return value technique to cancel the iteration in their .each() iterator. Adding that into your code, it would look like this:
Util.forEach=function(iterator,callback,context){
if (iterator.length && callback) {
for(var i = 0; i < iterator.length; i++){
var val=iterator[i];
if (callback.call(context||window,val,i) === false) {
break;
}
}
}
}
In the MDN documentation for forEach, you can see a sample implementation.
On the second issue, this type of implementaation does not permit insertion or deletion of elements at or before the iteration point because that will cause some elements to get skipped in the iteration or some objects to get iterated multiple times. The obvious way around that would involve making a copy of the object before iterating which is not efficient when not needed.

how to break the loop?
You're not supposed to break from forEach. That's why it's called "for each", and not "for some". "Breakable" JS iterators are every() (stops when the callback returns false) and some() (stops when the callback returns true).
Looking at your code once again it makes me think you actually want an indexOf kind of method, and not an iterator.
remove value of the array when iterator
Iterators shouldn't make any changes of the underlying array. You have to implement filter() and use it to generate a new array.
See js iteration methods for more details.

Related

Angular inner foreach break/continue unexpected behaviour

I have a nested foreach which I want to break out of if a condition is met. It seems that using a return means that the execution breaks out of the outer foreach, not the inner:
angular.forEach(objectA, function(objA, key) {
angular.forEach(ObjectB, function(objB, key) {
if(foo !== bar) {
return;
}
});
});
I read that it is better to use s native for each for this purpose, so I created this fiddle which works as I need it to:
https://jsfiddle.net/3dfx14nt/
However when I apply the logic to my Angular app it behaves in the same way as the Angular.foreach does. When returning on the inner foreach it breaks out to the outer foreach.
forEach accepts a function and runs it for every element in the array. You can't break the loop. If you want to exit from a single run of the function, you use return
forEach doesn't support break, you should use return
If you want to be able to break the loop, you have to use for..of loop:
for(let name of group.names){
if (name == 'SAM') {
break;
}
}

forEach/for...in not returning values? [duplicate]

This question already has answers here:
Function with forEach returns undefined even with return statement
(5 answers)
Closed 3 years ago.
So I have a little bit of confusion, I'm solving a challenge on freeCodeCamp.
The challenge reads as follows
Everything Be True
Check if the predicate (second argument) is truthy on all elements of a collection (first argument).
It's solved but I don't understand why I had to take an extra step. My code is as such:
function truthCheck(collection, pre) {
collection.forEach(function(element) {
for (key in element) {
if (!element.hasOwnProperty(pre)) {
return false;
} else if (key === pre) {
if (!Boolean(element[key])) {
return false;
}
}
}
});
return true;
}
truthCheck([
{"user": "Tinky-Winky", "sex": "male"},
{"user": "Dipsy"},
{"user": "Laa-Laa", "sex": "female"},
{"user": "Po", "sex": "female"}
], "sex");
so in this instance it should fail because the 2nd element within collection does not have the sex property. Also you will receive a fail if the pre argument, or in this case sex is not a truthy value.
When these get hit (Which they are, I'm able to tell through console logs) but I figure it would break out of the loop and return from the truthCheck function.....but it doesn't, and it will eventually return true.
I was able to circumvent this by defining a variable and then setting that value to false and then returning the variable at the end. Is there a better way? It seems like these returns should break out of the truthCheck function? Am I missing something?
As the other answers explain, this is meaningless:
collection.forEach(function () {
// do something
return false;
});
because array#forEach simply does not care for the return value of its worker function. It just executes the worker function for each array element.
You could use the worker function to set an outer variable:
function truthCheck(collection, pre) {
var allAreTruthy = true;
collection.forEach(function (elem) {
// if this ever flips allAreTruthy to false, it will stay false
allAreTruthy = allAreTruthy && elem[pre];
});
return allAreTruthy;
}
But there are better ways to express this.
Check if the predicate (second argument) is truthy on all elements of a collection (first argument).
Could be paraphrased as "Every element of the collection has a truthy value at a particular key."
function truthCheck(collection, pre) {
return collection.every(function (elem) { return elem[pre]; });
}
Could be paraphrased as "None of the elements of the collection have a falsy value at a particular key (or are missing the key entirely)."
Or, since an Array#none method does not actually exist, "There aren't some elements of the collection that have a falsy value at a particular key."
function truthCheck(collection, pre) {
return !collection.some(function (elem) { return !elem[pre]; });
}
The advantage of using Array#some is that it stops iterating the array as soon as the condition it seeks for is fulfilled. If your array had many elements this would mean improved performance. For short arrays there's not a lot of difference to using Array#every or Array#forEach.
The above is semantically equivalent to
function truthCheck(collection, pre) {
var i;
for (i = 0; i < collection.length; i++) {
if (!collection[i][pre]) return false;
}
return true;
}
Since JS objects simply return undefined when you access a key that has not been set, a check for hasOwnProperty is superfluous here.
You can't return anything from a ForEach loop. It will return undefined by default.
As the official documentation, Array.prototype.forEach() - JavaScript | MDN, says:
There is no way to stop or break a forEach() loop other than by throwing an exception. If you need such behavior, the forEach() method is the wrong tool, use a plain loop instead. If you are testing the array elements for a predicate and need a Boolean return value, you can use every() or some() instead.
So you can use a very simple for..in loop, for example:
for(var c in collection){
// Do whatever you want
}
[collection].forEach of javascript does not work like an ordinary loop. There is no way to prematurely end it not unless you make it throw an exception.
The behavior that you are expecting is what you would expect out of a javascript for loop but since forEach uses callback functions for each looped object, then you are only exiting the callback function instead of the forEach. Also it is worth noting that in your code, the you have a for loop which has a return in it. The return block in this loop only breaks this loop and not the forEach (which I have mentioned earlier, cannot be prematurely terminated unless otherwise)
As you can see forEach is mostly meant to iterate all elements instead of conditional checks per iterated element.
function truthCheck(collection, pre) {
return collection.every(function (person) { return !!person[pre]; });
}
you execute a function on each element of the collection. This function checks that element an returns something. But that returned value does not affect the result of the outer function. Since the outer function does not depend on the inner function your result is allways true.
if you define a variable, set this to false and return that variable at the end would works but it would be inefficient. Lets think of the following scenario. You found one element which does not has the target key. So right now you should return but you can't. You have to working yourself through the whole collection. The forEach loop does not give you the chance to exit without a mess. Thus a better idea is the for loop. Your can exit exit the for loop if found what you were looking for
a slightly easier way would be:
function truthCheck(collection, pre) {
//iterate thrugh your collection
for (var c in collection){
//get keys of element as an array and check if pre is in that array
if( Object.keys(collection[c]).indexOf(pre) == -1){
// pre was not found
return false;
}
}
return true;
}

Why does my code not detect a match?

I have some code that is comparing a string against values in an array:
var blacklistedSites = ['https://www.google.com/_/chrome/newtab?espv=2&ie=UTF-8'];
//Returns true if the current site is blacklisted, false otherwise
function isBlacklistedSite(url) {
console.log('Site is ' + url);
blacklistedSites.forEach(function(entry) {
console.log('testing ' + entry);
if (entry == document.URL) {
return true;
}
});
return false;
}
console.log(isBlacklistedSite('https://www.google.com/_/chrome/newtab?espv=2&ie=UTF-8'));
This outputs:
Site is https://www.google.com/_/chrome/newtab?espv=2&ie=UTF-8
testing https://www.google.com/_/chrome/newtab?espv=2&ie=UTF-8
false
Why does isBlacklistedSite() not detect a match?
The reason your code doesn't work is that your:
return true;
effectively does nothing. It just returns from the forEach function, which happens anyway regardless of there being a match, or not. Your return true; does not return from your isBlacklistedSite() function. Your isBlacklistedSite() function always exits with:
return false;
While you could do this using .forEach(), it is a poor choice. The .forEach() method always iterates over every member of the array, regardless of any return value you provide in the forEach function. You would only use it if you were also doing some other operation on every element of the array at the same time. Even then, it might be better to separate out the two different tasks. If you did use it, you would have to keep the detection in a variable defined external to the .forEach(function(){....
Use .indexOf() to test an exact match to an array element
If you want to test for exact matches of Array elements, you can use .indexOf() and test for a value > -1.
For instance:
var blacklistedSites = ['https://www.google.com/_/chrome/newtab?espv=2&ie=UTF-8'];
function isBlacklistedSite(url) {
console.log('Site is ' + url);
return blacklistedSites.indexOf(url) > -1;
}
//Test with a known matching value.
console.log(isBlacklistedSite(blacklistedSites[0]));
//Test with a known failing value.
console.log(isBlacklistedSite('foo'));
If you need a more complex test, you can use .some()
var blacklistedSitesRegExes = [/(?:https?:)?\/\/[^/]*www\.google\.com\/.*espv=2/];
function isBlacklistedSite(url) {
console.log('Site is ' + url);
return blacklistedSitesRegExes.some(function(regex){
regex.lastIndex = 0; //Prevent contamination from prior tests
return regex.test(url);
});
}
//Test with a known matching value.
console.log(isBlacklistedSite('https://www.google.com/_/chrome/newtab?espv=2&ie=UTF-8'));
//Test with a known failing value.
console.log(isBlacklistedSite('foo'));
With limited availability: .includes() (not for production code)
.includes() does exactly what you want (return a Boolean true/false for an exact match). However, it is not as generally available as .indexOf(). It is recommended not to use it in production code. For Arrays, it does not add much benefit over .indexOf(url) > -1.
Additional methods
There are many additional methods available to Arrays which could be used to determine that you have a match. What you use will depend on your specific needs. As always, you should be mindful of compatibility issues for any method you choose to use. Some of the available methods are (text from MDN):
Array.prototype.every()
Returns true if every element in this array satisfies the provided testing function.
Array.prototype.filter()
Creates a new array with all of the elements of this array for which the provided filtering function returns true.
Array.prototype.find() (no IE)
Returns the found value in the array, if an element in the array satisfies the provided testing function or undefined if not found.
Array.prototype.findIndex() (no IE)
Returns the found index in the array, if an element in the array satisfies the provided testing function or -1 if not found.
Array.prototype.includes() (compatibility issues, including no IE)
Determines whether an array contains a certain element, returning true or false as appropriate.
Array.prototype.indexOf()
Returns the first (least) index of an element within the array equal to the specified value, or -1 if none is found.
Array.prototype.lastIndexOf()
Returns the last (greatest) index of an element within the array equal to the specified value, or -1 if none is found.
Array.prototype.some()
Returns true if at least one element in this array satisfies the provided testing function.
Could be used, but not very appropriate:
Array.prototype.forEach()
Calls a function for each element in the array.
Array.prototype.map()
Creates a new array with the results of calling a provided function on every element in this array.
Array.prototype.reduce()
Apply a function against an accumulator and each value of the array (from left-to-right) as to reduce it to a single value.
Array.prototype.reduceRight()
Apply a function against an accumulator and each value of the array (from right-to-left) as to reduce it to a single value.

Looping through array in if statement to check if all values pass

I have a variable 'fieldCount' that is equal to 5 (the number of fields I have). How can I write the following out without specifically stating each index:
if (
fields[0].checkValidity() && fields[1].checkValidity() && fields[2].checkValidity()
&& fields[3].checkValidity() && fields[4].checkValidity()
) {
fieldsPass = true;
}
You can use a loop, or some fairly standard built-in browser functions.
Loop
Here's how to do it with a loop. This should be the fastest code, but you probably don't need the fastest code unless you are checking a huge number of fields on a huge number of items. I recommend instead the "correct, clear, concise, fast" priorities, so think you should start with the built-in browser functions. But here it is for reference:
var fieldsPass = true;
var i, l = fields.length;
for (i = 0; i < l; i += 1) {
if (fields[i].checkValidity()) continue;
fieldsPass = false;
break;
}
Note that declaring the i variable outside of the loop and capturing the field length outside the loop are optional.
The first I did because many people don't know about hoisting, and the fact that for (var i ... does NOT create a variable only available inside the for loop, it is the same as having declared var i at the top of the function, and this behavior can lead to bugs.
The second I did out of habit, though as I said you can put it inside the loop check. See this discussion. If you do use the loop method, you're probably looking for better performance, so might want to use the captured length way for the best possible performance. (And if it really matters that much, you can do the var i = fields.length; while (i--) { } method.)
Browser Function Array.Every
You can use Array.prototype.every() (from ECMAScript 2015 6th edition):
Mozilla Developer Network
The every() method tests whether all elements in the array pass the test implemented by the provided function.
fieldsPass = fields.every(function(field) {
return field.checkValidity();
});
It returns truewhen the passed-in function, when run on every item in the array, returns true for all of them. If any one returns false, it stops and returns false. In some languages, they call the same concept all, if you're familiar with that.
Alternately, it might be better to declare your checkValidity function once, instead of putting it on every field. This may not be possible, depending on how you implemented it (perhaps it has access to private variables?). Notice that the first argument of the callback function you provide (see the documentation in the links above) is the currentValue of the iteration, the field you want to check. If your function thus looks like this, it will work:
function checkValidity(field) { /* check validity */ }
fieldsPass = fields.every(checkValidity);
Browser Function Array.Some
You can use also Array.prototype.some() (from ECMAScript 2015 6th edition):
Mozilla Developer Network
The some() method tests whether some element in the array passes the test implemented by the provided function.
fieldsPass = !fields.some(function(field) {
return !field.checkValidity();
});
Notice that it is basically just the inverse of every, as "ALL VALID" is the same as "NOT (ANY INVALID)". It just means that it checks for any one item in the array that passes the function, and if so, returns true. In some languages, they call the same concept any, if you're familiar with that.
General Browser Compatibility Notes
Note that for these two functions, browser compatibility is pretty good. If you don't care about IE below version 9 then you're pretty much safe. If you do, then you would want to use a polyfill, which is available on the above-linked MDN pages. You would include that code in the global scope of your javascript file, and then would be able to use it as normally in IE 8 and below. (I'm talking about the code block starting like this:)
if (!Array.prototype.every) {
Array.prototype.every = function(callbackfn, thisArg) {
...
}
You have an array of fields, and you want to iterate them, and invoke a validity check method on each of them. Only if all of them pass, the flag fieldsPass would be true.
This is exactly the behavior of Array#every. According to MDN:
The every() method tests whether all elements in the array pass the
test implemented by the provided function.
Use Array.every to invoke checkValidity() on each field. If all fields are valid, the result would be true. If one field fails checkValidity(), the loop would return false immediately, without checking the other fields.
var fieldPass = fields.every(function(field) {
return field.checkValidity();
})
Like you said, use a loop.
var fieldsPass = true;
for (var i = 0; i < fields.length; i++) {
// Exit early if one of them fails
if (!fields[i].checkValidity()) {
fieldsPass = false;
break;
}
}
You can use the .some() method and reverse the logic to tell if all passed like so:
var allPassed = !fields.some(function (field) {
return !field.checkValidity();
});
You can do it like this:
fieldsPass = true;
for (i = 0; i < fieldCount; i++)
{
if(!fields[i].checkValidity())
{
fieldsPass = false;
break;
}
}

Recursive JavaScript function is losing the return value

I want to search a string in a nested JSON object. If the string found in an object, I need to return that object.
I am using a recursive function to achieve this. The problem is, the function is recursing until the end and not returning the object found.
Please see the entire code in jsfiddle
function search(obj, name) {
console.log(obj["name"], ",", name, obj["name"] == name);
if (obj["name"] == name) {
return obj; //NOT RETURNING HERE
}
if (obj.children || obj._children) {
var ch = obj.children || obj._children;
//console.log(ch);
ch.forEach(function(val) {
search(val, name)
});
}
return -1;
}
search(myJson, "VM10-Proc4")
I am not sure what is going wrong.
You need to stop looping over children when it finds one that matches.
function search(obj, name) {
console.log(obj.name, ",", name, obj.name == name);
if (obj.name == name) {
return obj;
}
if (obj.children || obj._children) {
var ch = obj.children || obj._children;
for (var i = 0; i < ch.length; i++) {
var found = search(ch[i], name);
if (found) {
return found;
}
}
}
return false;
}
FIDDLE demo
The correct return value is getting lost in the chain of recursive function calls. After the correct value is found, any additional searches made will return incorrect values from that point on.
A couple ways to handle this:
1. Cancel the search
When the correct value is found, immediately return it all the way up the recursive stack, without searching any more of the current arrays or the nested arrays. In other words, cancel the rest of the search.
#Barmer's answer is an example of this. The key part of his code is the use of for loops rather than the each method to iterate through the arrays, since it's much easier to interrupt a for loop.
2. Store the value somewhere safe
When the correct value is found, store it somewhere safe, allow the rest of the search to continue, and after the initial function call has finished access the value. The simplest way is to store the correct value in a global variable, though that's not a good practice as it violates the encapsulation of the function.
#shyam's answer presents a cleaner solution: Passing a reference to a global variable as a function parameter, setting the parameter when the correct value is found, and then accessing the global variable after the initial function call has finished.
Choosing between the two
In laymen's terms, the intended logic of the function could be summed up as follows: When you find what you're looking for, stop, and let me know what it is immediately. The only reason to continue searching would be if multiple pieces of data needed to be found. I'm assuming that's not the case here.
Of the two approaches, #2 is a quick-fix workaround that should work fine but will further confuse anyone who's trying to understand the intended logic of the function. Why is the search continuing if it's only looking for a single piece of data that's already been found?
#1 is a refactoring of the function so that it behaves more consistently with the intended logic, which would make the function easier to understand. The function stops searching when it finds what it needs.
I know this is an old post, but I can see 2 issues with this:
1) the recursive call isn't returning the result up the call stack i.e.
search(val, name)
Should be
return search(val, name)
2) it looks like you are using array.forEach(). The documentation states:
There is no way to stop or break a forEach() loop other than by throwing an exception. If you need such behavior, the forEach() method is the wrong tool. Use a plain loop instead. If you are testing the array elements for a predicate and need a Boolean return value, you can use every() or some() instead. If available, the new methods find() or findIndex() can be used for early termination upon true predicates as well.
What this means is, effectively, when you find the result you are looking for you want to send it back up the call stack. Using array.forEach will continue to recursively look through the hierarchy and return all values, not just the one you are interested in. Therefore the last returned value maybe one you don't expect, like undefined! Therefore use a different method of iterating i.e.
for (var i = 0; i < ch.length; i++) {
var val = ch[i];
return search(val, name, ret);
}
The accepted answer does spoon feed you part of this answer but doesn't explain why. Hence this answer
Since you are recursing the return might be nested too deep for you to get a meaningful result. Instead you can try passing an extra argument to collect the results.
function search(obj, name, ret) {
console.log(obj["name"], ",", name, obj["name"] == name);
if (obj["name"] == name) {
ret.push(obj);
return
}
if (obj.children || obj._children) {
var ch = obj.children || obj._children;
ch.forEach(function(val) {
search(val, name, ret);
});
}
}
var result = [];
search(myJson, "VM10-Proc4", result)
Here is a solution using object-scan
// const objectScan = require('object-scan');
const myJson = {"name":"UCS - San Jose","type":"Minor","children":[{"name":"VM1","type":"Clear","children":[{"name":"VM1-Proc1","type":"Clear","children":[{"name":"VM1-Proc1-child1","type":"Clear"}]},{"name":"VM1-Proc2","type":"Clear"},{"name":"VM1-Proc3","type":"Clear"},{"name":"VM1-Proc4","type":"Clear"},{"name":"VM1-Proc5","type":"Clear"},{"name":"VM1-Proc6","type":"Clear"},{"name":"VM1-Proc7","type":"Clear"},{"name":"VM1-Proc8","type":"Clear"},{"name":"VM1-Proc9","type":"Clear"},{"name":"VM1-Proc10","type":"Clear"}]},{"name":"VM2","type":"Clear","children":[{"name":"VM2-Proc1","type":"Clear"},{"name":"VM2-Proc2","type":"Clear"},{"name":"VM2-Proc3","type":"Clear"},{"name":"VM2-Proc4","type":"Clear"},{"name":"VM2-Proc5","type":"Clear"},{"name":"VM2-Proc6","type":"Clear"},{"name":"VM2-Proc7","type":"Clear"},{"name":"VM2-Proc8","type":"Clear"},{"name":"VM2-Proc9","type":"Clear"},{"name":"VM2-Proc10","type":"Clear"}]},{"name":"VM3","type":"Clear","children":[{"name":"VM3-Proc1","type":"Clear"},{"name":"VM3-Proc2","type":"Clear"},{"name":"VM3-Proc3","type":"Clear"},{"name":"VM3-Proc4","type":"Clear"},{"name":"VM3-Proc5","type":"Clear"},{"name":"VM3-Proc6","type":"Clear"},{"name":"VM3-Proc7","type":"Clear"},{"name":"VM3-Proc8","type":"Clear"},{"name":"VM3-Proc9","type":"Clear"},{"name":"VM3-Proc10","type":"Clear"}]},{"name":"VM4","type":"Minor","children":[{"name":"VM4-Proc1","type":"Clear"},{"name":"VM4-Proc2","type":"Clear"},{"name":"VM4-Proc3","type":"Minor"},{"name":"VM4-Proc4","type":"Clear"},{"name":"VM4-Proc5","type":"Clear"},{"name":"VM4-Proc6","type":"Minor"},{"name":"VM4-Proc7","type":"Clear"},{"name":"VM4-Proc8","type":"Clear"},{"name":"VM4-Proc9","type":"Clear"},{"name":"VM4-Proc10","type":"Clear"}]},{"name":"VM5","type":"Clear","children":[{"name":"VM5-Proc1","type":"Clear"},{"name":"VM5-Proc2","type":"Clear"},{"name":"VM5-Proc3","type":"Clear"},{"name":"VM5-Proc4","type":"Clear"},{"name":"VM5-Proc5","type":"Clear"},{"name":"VM5-Proc6","type":"Clear"},{"name":"VM5-Proc7","type":"Clear"},{"name":"VM5-Proc8","type":"Clear"},{"name":"VM5-Proc9","type":"Clear"},{"name":"VM5-Proc10","type":"Clear"}]},{"name":"VM6","type":"Minor","children":[{"name":"VM6-Proc1","type":"Clear"},{"name":"VM6-Proc2","type":"Clear"},{"name":"VM6-Proc3","type":"Minor"},{"name":"VM6-Proc4","type":"Clear"},{"name":"VM6-Proc5","type":"Clear"},{"name":"VM6-Proc6","type":"Clear"},{"name":"VM6-Proc7","type":"Minor"},{"name":"VM6-Proc8","type":"Clear"},{"name":"VM6-Proc9","type":"Clear"},{"name":"VM6-Proc10","type":"Clear"}]},{"name":"VM7","type":"Clear","children":[{"name":"VM7-Proc1","type":"Clear"},{"name":"VM7-Proc2","type":"Clear"},{"name":"VM7-Proc3","type":"Clear"},{"name":"VM7-Proc4","type":"Clear"},{"name":"VM7-Proc5","type":"Clear"},{"name":"VM7-Proc6","type":"Clear"},{"name":"VM7-Proc7","type":"Clear"},{"name":"VM7-Proc8","type":"Clear"},{"name":"VM7-Proc9","type":"Clear"},{"name":"VM7-Proc10","type":"Clear"}]},{"name":"VM8","type":"Clear","children":[{"name":"VM8-Proc1","type":"Clear"},{"name":"VM8-Proc2","type":"Clear"},{"name":"VM8-Proc3","type":"Clear"},{"name":"VM8-Proc4","type":"Clear"},{"name":"VM8-Proc5","type":"Clear"},{"name":"VM8-Proc6","type":"Clear"},{"name":"VM8-Proc7","type":"Clear"},{"name":"VM8-Proc8","type":"Clear"},{"name":"VM8-Proc9","type":"Clear"},{"name":"VM8-Proc10","type":"Clear"}]},{"name":"VM9","type":"Clear","children":[{"name":"VM9-Proc1","type":"Clear"},{"name":"VM9-Proc2","type":"Clear"},{"name":"VM9-Proc3","type":"Clear"},{"name":"VM9-Proc4","type":"Clear"},{"name":"VM9-Proc5","type":"Clear"},{"name":"VM9-Proc6","type":"Clear"},{"name":"VM9-Proc7","type":"Clear"},{"name":"VM9-Proc8","type":"Clear"},{"name":"VM9-Proc9","type":"Clear"},{"name":"VM9-Proc10","type":"Clear"}]},{"name":"VM10","type":"Clear","children":[{"name":"VM10-Proc1","type":"Clear"},{"name":"VM10-Proc2","type":"Clear"},{"name":"VM10-Proc3","type":"Clear"},{"name":"VM10-Proc4","type":"Clear"},{"name":"VM10-Proc5","type":"Clear"},{"name":"VM10-Proc6","type":"Clear"},{"name":"VM10-Proc7","type":"Clear"},{"name":"VM10-Proc8","type":"Clear"},{"name":"VM10-Proc9","type":"Clear"},{"name":"VM10-Proc10","type":"Clear"}]}]};
const search = (obj, name) => objectScan(['**.name'], {
rtn: 'parent',
abort: true,
filterFn: ({ value }) => value === name
})(obj);
console.log(search(myJson, 'VM10-Proc4'));
// => { name: 'VM10-Proc4', type: 'Clear' }
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan#13.7.1"></script>
Disclaimer: I'm the author of object-scan

Categories

Resources