We have object type variable in Jquery:
var obj = *{"1234" : "xx", "4321" : "yy", "5555" : "hh", "2321" : "aa" };*
Lets say that I want to delete every property from property name "5555" to the end of the object(that means that I want to delete obj['5555'] and delete obj['2321'] ).
I am interested in smartest way, trough loop, to do that.
In array I would use splice(2, arr.length) but I am confused.
There's no guarantee as to the order of an object's properties. When pasting your example object in my console, Here's what I saw:
> obj = {"1234" : "xx", "4321" : "yy", "5555" : "hh", "2321" : "aa" }
Object {1234: "xx", 2321: "aa", 4321: "yy", 5555: "hh"}
As you can see, chrome ordered the properties in ascending order, like it would an array. Who knows, but maybe IE doesn't do this... Maybe some obscure browser would order the properties in descending order... There's no way of knowing what the actual object will look like, so perhaps have a rethink.
If all your properties are, essentially numeric, there's nothing wrong with using an array, in JS, the Array prototype is nothing but an augmented Object:
obj = [];
obj[1234] = 'xx';
obj[2321] = 'aa';
obj[5555] = 'hh';
The numeric indexes are coerced to strings internally anyway (because Array's are objects), so JS isn't going to create endless empty indexes for you, it resolves obj[200] just like it would resolve objectLiteral.undefinedProperty: scan instance, then prototypechain. If the requested property wasn't found, return undefined.
They're added as you go along, yet here are 2 ways:
//Assume simpel object (non-nested)
var newObj = JSON.parse(JSON.stringify(obj).replace(/\{|,\s*"5{4}"\s*:.+$/,'}'));
This, I think, is the easiest way, but not very reliable. The most "tried and tested" apprach is:
var unset = false;
for (var prop in obj)
{
if (obj.hasOwnProperty(prop))
{
unset = unset || !!(prop === '5555');
if (unset === true)
{
delete(obj[prop]);
}
}
}
The last approach creates an array, containing all keys, which you can iterate over, and delete the properties that way. It's here for completeness' sake only: I wouldn't use it, though, simply because it requires a browsers that supports the ES5 spec (not all browsers do, sadly), and there's no real advantage over the code above:
var keys = Object.keys(obj).sort(),//call sort to assure ascending order
toDelete = keys.splice(keys.indexOf('5555'), keys.length).sort();
for(var i=0;i<toDelete.length;i++)
{
delete obj[toDelete[i]];
}
Push the obj to be searched and the value to be found into a function that returns a new object with only those properties up to the value you specified.
function returnNewobj(obj, value) {
var newObj = {};
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
if (prop === value) return newObj;
newObj[prop] = obj[prop];
}
}
return newObj;
}
Edit: probably not necessary, but I added the hasOwnProperty line to be on the safe side.
Edit2: It's worth pointing out that new properties are added to objects in alphanumerical order, not to the end of objects like elements are added to arrays. So don't get caught out by that.
I would recommend you to get the index of the element from which you want to start deleting elements and then looping throw the object deleting the elements with a higher index.
You might want to create a function to make it more similar to splice i you prefer.
Find the element you are looking for and set that particular element and any element after that to null.
Its very tricky to delete property name however property value can be made null or undefined but removing property is difficult but you can do one thing can copy the required properties in new object its a workaround though here is a sample fiddle i use this often in this kind of situation
objCopyTo[strToPropertyName] = objCopyFrom[strPropertyName];
here is the fiddle
Related
I'm renaming the keys of an object while iterating them:
Object.keys(object).forEach(function(oldKey) {
var newKey = someFunc(oldKey);
if (newKey !== oldKey) {
object[newKey] = object[oldKey];
delete object[oldKey];
}
}
And I would like to know if this method is safe.
In other words, can I be sure that my code will never iterate a key which has been renamed in a previous iteration?
No, you aren't safe. You're mutating the object live, based on an array that is not live. If you happen to cross a new name with an old (rename a to b, but b already exists and haven't been reached yet) you're going to have a bad time.
You will not come across keys you've already seen, but you have no way to know whether the newKey is not already found in the object.
There are workarounds, the situation is similar to .splice()ing an array (removing elements) while you iterate it, and the simple workaround is to iterate backwards, so that you always already pass the altered keys. (Or in your case, checking with the in operator)
You're much better, however, creating and returning a new object:
const newObj = Object.keys(object).reduce(function(result, oldKey) {
var newKey = someFunc(oldKey);
return { ...result, [newKey]: object[oldKey] };
}, {});
You get a lot of things for free when you treat all of your data structures as immutables (and more specifically, when the keys never change)
Object.keys, like many other methods, returns an Array that you can iterate over. This Array is not "live" but a snapshot from the time of taking it (e.g. executing Object.keys). So yes, you're save to use it as intended.
There are very little examples of methods that return "live lists" instead of an Array; I guess you're having NodeLists in mind, that you'll get when using document.querySelectorAll. This however not an Array but a NodeList.
However, there may be one pitfall I can see is: When a generated newKey already exists in the list of oldKeys (not the current one!). So you may or may not (depending on the position in the array) iterate over the already overwritten new key.
Here is a solution to change the key without creating a new Object.
for(key in obj){
Object.defineProperty(obj, `myNewName`, Object.getOwnPropertyDescriptor(obj, key));
delete obj[key];
}
I am new in javascript.
Here I am wondering about how many nested or inner object could i
define in javascript
how to find first 2 nested object's key in js.
i also search it on google but i didn't get any solution.
here is example what i want!
var obj = {
a:{
b:{
c:{
//so on
}
}
}
}
thanks in advance.
Here I am wondering about how many nested or inner object could i define in javascript
There is no specified limit.
In the case of an object initializer such as the one you've shown, eventually you'll run into some sort of limitation of a particular JavaScript engine running the code, e.g., around its parsing / processing of the initializer, but nothing defined in the specification.
If you build objects dynamically on your own, for instance like this:
// Don't run this code!
var obj = {};
while (true) {
obj.child = {};
obj = obj.child;
}
...there's no reason to believe you'll run into anything other than a memory limit related to the number of objects you're creating (not their nesting).
how to find how many objects keys are defined in js
In one particular object, you can get an array of its own (not inherited) properties via Object.getOwnPropertyNames and Object.getOwnPropertySymbols, then take the length of the array. To find out how many properties the object has and how many the objects its properties refer to have, you'd use a recursive search — but beware of cyclic structures.
For instance:
const obj = {
a: {
b: {
c: {
}
}
}
};
function countProps(target, recursive = false) {
const ownProperties = [
...Object.getOwnPropertyNames(target),
...Object.getOwnPropertySymbols(target)
];
let count = ownProperties.length;
if (recursive) {
for (const key of ownProperties) {
const value = target[key];
if (value && typeof value === "object") {
count += countProps(value, true);
}
}
}
return count;
}
console.log(countProps(obj, true));
answer for first question.
There is not any restriction for nested object. you can define nested object as per you want until your memory limit exceed.
answer for second question.
here is a code to find keys from nested objects but it is work for only 2nd nested object.
for (var key in ob) {
if (!ob.hasOwnProperty(key))
continue;
var obj = ob[key];
help += "</br>"
for (var prop in obj) {
// skip loop if the property is from prototype
if(!obj.hasOwnProperty(prop)) continue;
help += " ---) \""+key+" "+prop+"\"</br>"
}
}
tell me if you got what you want.
Here I am wondering about how many nested or inner object could i define in javascript?
In the specification of JS it is not defined.
You can define nested or inner object how many you want.
But: do not forget: every object in your code need place in PC memory. And if you have to many objects you browser will not work correctly.
How to find how many objects keys are defined in JS?
With following metods:
Object.getOwnPropertyNames
Returns an array containing the names of all of the given object's own enumerable and non-enumerable properties.
Object.getOwnPropertySymbols
Returns an array of all symbol properties found directly upon a given object.
you will find the length of how many objects keys are defined in your object.
I am very new to JavaScript and I am trying to figure out how to set a function to remove the last key:value pair to the right, much like array.pop for an array. This is an assignment I am working on. It seems confusing to me because, from my limited understanding of JS their is no specific order in a list of properties in an object. If anyone has any insight I would appreciate it. Here is the object:
var array = {length:0, size:big, smell:strange};
this is where I have started to go, but just having a hard time completing the function:
array.pop = function() {
//...
};
Ultimately I would like it to turn out like this:
array = {length:0, size:big};
Thanks in advance.
Objects do not have any defined order of properties so there is no "last" property. You have to remove a property by name, not position.
You can, of course, iterate over the properties and inspect them as you iterate and decide whether you want to delete any given property by looking at its name. Some javascript implementations will preserve the order that properties were added, but that is specifically not guaranteed by the ECMAScript specification so it cannot be relied upon.
This will work
const car = {
color: 'blue',
brand: 'Ford'
}
let keys = Object.keys(car)
delete car[keys[keys.length-1]]
console.log(car)
This answer is good for those situtations where the key is dynamically generated numbers like 0,1,2,3,4 etc
const myObject = {
0: 'somestring',
1: 42,
2: false
};
delete myObject[`${Object.keys(myObject).length-1}`]
console.log(myObject);
output:
Object { 0: "somestring", 1: 42 }
this one line logic may not good when key is a string. So, carefully use it.
The snippet below demonstrates that "objects have no order", and an [inefficient] workaround: use an array alongside of the object, to store the order that the properties were added to the object.
Click to add random properties, and note the order that they appear below.
In CodePen (or on my webserver) the properties seem to be stored sorted numerically (even though they're stored as strings).
However, in the snippet below they seem to be ordered randomly.
Neither are the order that the properties are added.
It should be noted:
Unlike what common belief suggests (perhaps due to other programming languages like delete in C++), the delete operator has nothing to do with directly freeing memory. Memory management is done indirectly via breaking references.
More info: delete operator and Memory Management.
var obj={}, // object to store properties (keys) and values
props=[]; // array to store property names
add.onclick=function(){
var prop=rnd(), val=rnd(); // get 2 random numbers
obj[ prop ] = val; // add property & value → object
props.push( prop ); // add property name → array
updateInfo(); // display object
}
del.onclick=function(){
var lastProp=props.pop(); // get/remove last property name in array
delete obj[ lastProp ]; // remove property
updateInfo(); //display object
}
function rnd(){return Math.floor(Math.random()*1E5);} // random 0-99999
function updateInfo(){ // show pretty object 😘
info.innerHTML=JSON.stringify(obj).replace(/[\{\}]+/g,"").replaceAll(',','<br>');
}
<button id='add'>add new property</button>
<button id='del'>delete last added</button>
<div id='info'></div>
I'm looking for an efficient way to test whether or not a JavaScript object is some kind of ordered object. Hopefully someone knows a trick that doesn't involve writing some huge type assessor function. Fortunately, I don't have to deal with IE < 9 so most of the newer methods are OK.
The fundamental problem is this: I need to figure out whether or not to run a for loop or a for...in loop on an object. However, I don't always know if the object is going to be an object literal, an array, a jQuery object, etc.
Here are some of the obstacles I'm running up against:
I clearly can't only use typeof because both arrays and objects return object.
I clearly can't only use Object.prototype.toString.call(collection) because, while arrays do return [object Array], custom ordered collections such as jQuery objects still return [object Object] and the whole reason I want this test is to determine whether I need a for loop or a for...in loop. Using a for...in loop on a jQuery object includes properties that aren't actually part of the collection and messes things up.
I did come up with one idea that looks like this:
function isOrdered(item) {
// Begin by storing a possible length property
// and defaulting to false for whether the item
// is ordered.
var len = item.length, isOrdered = false;
// Functions are an easy test.
if (typeof item === 'function') {
return false;
}
// The Arguments object is the only object I know of
// with a native length property that can be deleted
// so we account for that specifically too.
if (Object.prototype.toString.call(item) === '[object Arguments]') {
return true;
}
// Attempt to delete the item's length property.
// If the item is ordered by nature, we won't get
// an error but we also won't be able to delete
// this property.
delete item.length;
// So if the length property still exists as a
// number, the item must be an ordered collection.
if (typeof item.length === 'number') {
isOrdered = true;
}
// If we originally stored a custom length property,
// put it back.
if (len !== undefined) {
item.length = len;
}
// Return the result.
return isOrdered;
}
So far this technique has passed all of my tests but I'm worried about possible performance hits that could arise from deleting properties on custom objects and I'm not 100% confident I'm not missing something. Does anyone have any better ideas?
You can do something like this:
function isOrdered(item) {
var len = item.constructor.prototype.length;
return len === +len;
}
If 'item' is a js object this will evaluate to false but if it's an array or jQuery collection this will return true.
Note that things other than arrays can have numeric length properties (try checking the length of a function). If you might pass things like integers or functions you will need to do something more complicate, but this should catch all the cases you catch in your posted code. Also, I think deleting the length property can have unpredictable results so I would avoid that approach in favor something that does not mutate the object you are testing.
If your trick is working in Firefox, Chrome, and recent IE, I think it's probably okay....though a bit wonky.
Delete goes through and deletes the key and value from an object, rather than just clearing the reference. It will actually return false if it cannot delete the property, so you could tighten up your logic a bit further.
There's a bit of performance overhead to property deletion, and it does some weird stuff to regular objects currently in memory [see this article], but negligible depending on the browser. It really depends on how many collections you'd be doing this on at a time. For a single array/object/mystery, I think it would be fine. But for a nested collection of thousands of arrays, you might want to look into some other alternative.
Here's a JS perf if you're primarily concerned with performance:
http://jsperf.com/delete-vs-undefined-vs-null/3
update
Alternatively, if you are concerned with Jquery collections vs arrays, you could do something like the following:
if (foo.length != undefined) {
if (Array.isArray(foo)) {
// regular array. Could also do
// foo instanceof Array
}
else if(foo.constructor.toString().match(/jQuery/g)) {
// jquery collection
}
} else {
// not an ordered collection
}
I have some simple Javascript looping through an array of items (Tridion User Groups) to check if the user is a member of a specific group.
I can easily code around the issue shown below ( see && extensionGroup !== 'true') but I want to understand why the isArray = true is counted as a value in the array - any ideas?
The screenshot below demonstrates that the value extensionGroups has been set thus
var extensionGroups = ["NotEvenARealGroup", "Author", "ExampleGroupAfterOneUserIsActuallyIn"];
but returns the isArray value as a 4th value?
updated to show images a little clearer
You're using for in to iterate an array; don't do that. Use for (or forEach):
for(var i = 0; i < extensionGroups.length; i++) {
var extensionGroup = extensionGroups[i];
// ...
}
The reason this fails is because for in is used to iterate over an object's properties in JavaScript. Iterating over an array in this way means you get anything else assigned to it, such as this property or length.
And if you're able to use Array#forEach, it's probably most appropriate here:
extensionGroups.forEach(function(extensionGroup) {
// ...
});
For..in, technically speaking, doesn't iterate through values. It iterates through property names. In an array, the values ARE properties, under the hood. So when you iterate over them with for..in you get funky stuff like that happening.
Which highlights my next point: don't use for..in. Don't use it for arrays -- don't use it for anything, really. Ok -- maybe that's going a bit too far. How about this: if you feel the need to use for..in, think hard to see if it's justifiable before you do it.