I've noticed that if we insert an object {a: 1, b: 2, c: 3}, in database it'll be stored as {c: 3, b:2, a: 1}. Why is MongooseJS doing this?
Is it for Performance Gain (or) some other logic?
Could anyone please explain this to me in detail?
There is no such thing as properties order in object. If the order is important for you use an array.
The for...in statement iterates over the enumerable properties of an object, in original insertion order. For each distinct property [...]
However this seems to be implementation (browser) dependant.
In objects you can't rely on order of the properties as even various iteration methods may give various results.
Ordering of properties in objects is complex, as this answer explains: https://stackoverflow.com/a/38218582/893780
Even though it's not specified in the standard, normal property keys are stored in insertion order.
Internally, Mongoose uses a faster code path when cloning objects, that reverses the property order. It basically does this:
let oldObject = { a: 1, b: 2, c: 3 };
let newObject = {};
let keys = Object.keys(oldObject);
let i = keys.length;
while (i--) {
let k = keys[i];
let val = oldObject[k];
newObject[k] = val;
}
Because normal keys are stored in insertion order, newObject will be the reverse of oldObject:
{ c: 3, b: 2, a: 1 }
However, because this can cause issues in queries, Mongoose added an option retainKeyOrder to prevent this reversal.
However, according to the same answer that I linked to above, you still can't rely on any order being imposed when using Object.keys() or for..in.
Related
I was trying to make an interface and initialize its instance with another object properties by spread syntax.
I found something weird and wanted to find out why this can happen.
This is an example of what I want.
A: The object that I want to make as a result
A = { a: number, b: number, c: number, d: number }
B: The object I've got with DB query
B = {a: number,b: number,c: number,e: string}
C: The object that has a value I will insert manually
C = { d: boolean }
So I've declared an interface A, and used spread syntax to make an object of A with B object.
A_object = {...B_object }
What I expected was an object of A which has properties 'a', 'b', and 'c', or an error.
But the result was quite different.
Property 'e' also appeared, which doesn't exist in interface A.
Can anybody explain why this happens?
The spread operator is a JavaScript feature which does not know about the known properties of TypeScript-interfaces. All properties of B_object will therefore appear in A_object when A_object = { ...B_object }.
From a type-safety perspective, this is fine. Everything needed to construct a valid A instance is also present in B, so spreading B into A is considered to be valid.
You are probably looking for excess property checks. Those are not necessarily needed in a structural type system and there are only a select few places where TypeScript does perform them. And spreading objects is not one of those places. There is an open Issue requesting this and you can give it a thumbs up if you want to see it implemented.
Nim has OrderedTable how can I get the element by its index, and not by its key?
If it's possible - is this an efficient operation, like O(log n) or better?
import tables
let map = {"a": 1, "b": 2, "c": 3}.toOrderedTable
Something like
map.getByIndex(1) # No such method
P.S.
I'm currently using both seq and Table to provide both key and indexed access and wonder if it could be replaced by OrderedTable
type IndexedMap = ref object
list*: seq[float]
map*: Table[string, float]
There is no direct index access to ordered tables because of their internal structure. The typical way to access the elements in order is:
import tables
let map = {"a": 1, "b": 2, "c": 3}.toOrderedTable
for f in map.keys:
echo $f
Basically, accessing the keys iterator. If you click through the source link in the documentation, you reach the actual iterator code:
let L = len(t)
forAllOrderedPairs:
yield t.data[h].key
And if you follow the implementation of the forAllOrderedPairs template (it's recommended you are using an editor with jump to implementation capabilities to inspect such code easier):
if t.counter > 0:
var h = t.first
while h >= 0:
var nxt = t.data[h].next
if isFilled(t.data[h].hcode):
yieldStmt
h = nxt
No idea about performance there, but it won't be as fast as accessing a simple list/array, because the internal structure of OrderedTable contains a hidden data field with the actual keys and values, and it requires an extra conditional check to verify that the entry is actually being used. This implementation detail is probably a compromise to avoid reshuffling the whole list after a single item deletion.
If your accesses are infrequent, using the iterator to find the value might be enough. If benchmarking shows it's a bottleneck you could try freezing the keys/values iterator into a local list and use that instead, as long as you don't want to mutate further the OrderedTable.
Or return to your original idea of keeping a separate list.
I was at a meetup recently and one of the talks was about how you can use Webpack to require just the pieces of a package that you need. I believe that it is called tree shaking. I was wondering if there is a way to do this without Webpack? For instance can you specify exactly the pieces of code you need rather than the whole node module.
Any information about this would be great. I am just looking to learn something new.
Cheers,
There's a couple pretty simple ways:
In ES6, you can do what is called destructuring.
Here's an example with arrays:
var a, b, rest;
[a, b] = [10, 20];
console.log(a);
// expected output: 10
console.log(b);
// expected output: 20
[a, b, ...rest] = [10, 20, 30, 40, 50];
console.log(rest);
// expected output: [30,40,50]
This is destructuring by index, where a = array[0], b=array of index 1 (hyperlink barred bracket format), etc... Notice the ... operator, called the spread operator in ES6. Here is a link to that if you are curious about what it does, or how to use it.
You can also do the same with objects, consider:
const someRandomObject = {
a: 1,
b: 2,
};
const {a} = someRandomObject;
console.log(a) // expected output: 1
You are destructing, by name, only the properties you need from the object, so you are not pulling in a bunch of unused stuff. If you are not using ES6, you can do something similar with:
const someRandomObject = {
a: 1,
b: 2,
};
const a = someRandomObject.b;
console.log(a) // expected output: 2
Same thing as above, you are pulling out of someRandomObject the property you want, and nothing else. Note that the above way is pulling the value on the right side, so the name of the variable does not matter. These two ways are functionally equivalent (I believe).
If we take the following snippet as an example:
main() {
List<int> array = [1, 2, 3, 4];
List<int> newArray = change(array);
print(array); // [99, 2, 3, 4]
print(newArray); // [99, 2, 3, 4]
print(newArray == array); // true
}
change(List<int> array) {
var newArray = array;
newArray[0] = 99;
return newArray;
}
The original array gets mutated. I was expecting that by passing the array (object) to the change function and assigning a new variable to it that I could avoid mutation. I am aware that the built_collection library seems like the main go-to for immutable collections. Is there any native way the core library that would allow for a deep freeze or prevent side effects (operations inside another function)?
You can wrap an array in an UnmodifiableListView from dart:collection and pass this around instead of the array itself. I think this is the most basic buit-in way.
Objects are passed by reference. This is by design: objects are often large data structures and internally making a copy every time an object is passed to a function can be very inefficient. (This is the same approach as that used by other major object oriented languages.)
As a result, array and newArray are two names for the same underlying List in your code.
If you want to explicitly create a new list, just change
var newArray = array;
to:
var newArray = new List.from(array);
Note: I am using Nodejs which may or may not have subtle differences from vanilla ECMAscript's standards.
I have always heard that when using a for-each loop to iterate over the properties of an object, I should not count on the properties being in the same order. (even though in practice I have never seen a case where the objects were iterated over in a different order). In production, we have what I believe to be a typo where an object is created with an overwritten property.
var obj = {
a: 'a property',
b: 'another property',
c: 'yet another property',
a: 'woah we have another a?'
}
In Nodejs, am I guaranteed that the second a property containing the string 'woah we have another a?' will ALWAYS shadow the first a property containing the string 'a property'?
(even though in practice I have never seen a case where the objects were iterated over in a different order)
The following should give you a different order in V8 atleast.
var obj = {
"first":"first",
"2":"2",
"34":"34",
"1":"1",
"second":"second"
};
for (var i in obj) { console.log(i); };
// Order listed:
// "1"
// "2"
// "34"
// "first"
// "second"
As discussed here
ECMA-262 does not specify enumeration order. The de facto standard is to match
insertion order, which V8 also does, but with one exception:
V8 gives no guarantees on the enumeration order for array indices (i.e., a property
name that can be parsed as a 32-bit unsigned integer).
Remembering the insertion order for array indices would incur significant memory
overhead.
Though the above says the enumeration order is not specified but that is after the object is created. I think we can safely assume that insertion order should remain consistent, as there is no point for any engine to do otherwise and alter the insertion order.
var obj = {
"first":"first",
"2":"2",
"34":"34",
"1":"1",
"second":"second",
2: "two"
};
// gives result
{ '1': '1',
'2': 'two',
'34': '34',
first: 'first',
second: 'second' }