How to conditionally paste an array value in variable initialization? - javascript

I have a getter in pinia store and this getter should return a typed array of objects.
Some objects can be pasted only by specific conditions, but typescript is throwing an error (see screenshot).
I tried several methods of conditional pasting, but none of them worked for me. The method i used on screenshot is the best in my opinion, but it returns an empty array, that has to be destructed and paste nothing. But as we can see it throws an error.
I can't push this object to the array after initialization because this array is a getter of pinia store.

Related

Get vue object inside object into console

I have a object in my Vue called 'file'.
When I use console.log to look at its contents its as below in the picture
console.log(file);
But now I want to see the contents of exif so I tried
console.log(file.exif)
The problem is that its always 'undefined'. What am I doing wrong? Please help.
The first thing I notice is that exif doesn't have the ... that all the other properties have. This suggests that it doesn't have a property getter. As reactive properties all have getters it would suggest that this property was added later than the others without using Vue.set.
With that in mind it is worth noting that objects logged to the console are live. If you hover over the little blue i icon you'll get some indication of this. The console does not take a copy of the properties when you log an object. It will only grab the property values when you expand the object in the console.
So what I believe is happening is that the property exif does not exist at the point you are logging out the object but it is subsequently added before you click on the object in the console.
There are other things you can try logging to double check. e.g. console.log(JSON.stringify(file)) or console.log(Object.keys(file)). These should all confirm that the exif property does not exist at that point.

How does console.log determines what properties to print when printing an object?

I have a mongodb database and I am using mongoose with nodejs. When I console a mongoose object, I get the usual keys that I have defined in my schema.
console.log(mongooseObject);
/*
{
_id: 5b8b7d627defb42e3f6349ef,
name: 'John Doe',
}
*/
But when I tried to console it's keys using Object.keys(), it prints 5 keys that are not really the part of my schema and must being used internally by mongoose for various operations.
console.log(Object.keys(mongooseObject)) // [ '$__', 'isNew', 'errors', '_doc', '$init' ]
My question is, how does console.log determines what part of the object to be printed? When just logging the object directly, how does it work its way through these keys and their values to determine what to print?
Is there a toString() like function that a class defines which describes the JSON representation of an object? Something which is then used by console.log to actually print.
Edit: I'm getting a lot of mongoose related solutions suggessting me to use .toJSON() and .toObject(). Perhaps I should have made it clear that I'm not really looking for mongoose related stuff. I just used it's example because that's how I notice such peculiar behaviour. I'm just generally intereted in how javascript is working behind here. And can I write a Class where I can describe how an object being instanciated from it should be consoled?
Mongoose Object is a very complex object with lots of functions inside.
If you want to just convert the object the the pure mongo json document you can use toJSON() function, then you can easily use .keys.
console.log(Object.keys(mongooseObject.toJSON()))
I don't think this is the console printing different keys than the keys in the object at that moment. The reason you do get the objected printed correctly the first time is because the object you pass console.log is being read the moment you are looking at it, but if you were to log JSON.parse(JSON.stringify(mongooseObject)) you would probably come to the realization the object is empty at that moment
The reason Object.keys returns different results is because it will create an array out of the keys in that object the moment its called.
Ideally, you just wait for the object to actually be there before printing its keys. To help you with that, we would need more code.
Objects yield this behavior because they are passed by reference, read this stackoverflow post for excellent information on what that means.
It can print anything it wants.
console.log is actually not part of the Ecmascript language standard. While there is a WhatWG standard for the console API, a JavaScript implementation isn't required to implement it at all (although AFAIK all of them do), and even in that standard parts are explicitly implementation-defined.
So the short answer is that there isn't an answer. The longer answer is that it's almost certainly going to print keys, possibly internal slots like [[class]], etc. but it's going to depend greatly on the actual object you pass in.

Vue.js "Cannot read property ... of undefined" - Getting around this expected behavior

Is it known that if you display an Object's property in a Vue.js template, and the object is undefined - that will crash the component. Regular variables are no problem if they're undefined.
This behavior is a killjoy. In my situation, which seems pretty generic, what is the best way to avoid this problem?
So I store data in a NoSQL database i.e. Mongo, and have a Vue.js component to view and modify the documents in the collection. Which works well.
But if I add an Object with properties to my schema (for example address with zip, state...), and update the component to display them, now all the components in my webapp will crash that display these documents because the object isn't in the data. Only new documents (with the new object) will show correctly, unless I go thru the database and add this "address" object to every existing document.
It would be great if the template could give the user an opportunity to view blank or add data that isn't already in the database.
What is a best practice in such a situation?
Should objects simply be avoided here?
This doesn't really have anything to do with Vue. You're dealing with a javascript error here. You can't reference a property of a null/undefined variable. The easy way around this is to use the && operator to check for the object.
someObj && someObj.property
If someObj is falsy, the right side is never evaluated. Note that when the left side is truthy, && returns the right side. Details: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_Operators
If you want a specific blank value, you can do this
someObj ? someObj.property : "Default value"

_.deepClone of an object, does not equal the old object?

I have a user object, and I want to track changes in case the user edits their information, however they can say 'discard changes' and it returns to the previous state of the user object on load.
My solution was to deepClone the original object into a backup var, to give it it's own reference points, then compare the user object to the backup object --- again using lodash
I watch the object using angular #$watch, and if !_.isEqual(user, backup).
$scope.$on '$routeChangeStart', (e, next) ->
if !_.isEqual(user, backup)
console.log 'changes made'
However this returns false, even when there are no changes? It's as if the two objects are not equal any longer, even though all the keys and values are identical? I assume more happens than what I see when I deepClone.
Any better approaches? And what am I doing wrong?
The problem is most likely that user has been altered by angular. Angular adds some properties for tracking to objects bound to the view (these properties start with $ or $$). If your objects don't have such 'native' properties, you could try to do a deepOmit on user first.
This is a classic example when the concept of immutability would help a lot. If your object would be immutable a copy of it would only mean a pointer to the original object and comparisons are thereby more robust in my opinion. Check out https://facebook.github.io/immutable-js/ if you would like to know why facebook has embraced it (and maybe try using it yourself).

How do I switch between making two variable names be an alias of the same object to making them equal two separate objects?

I have two objects, obj1 and obj2. I want one to have the same properties and values as the other when the user clicks a button, so I write this line:
main.obj1.data=$.extend({},main.someArray[0].data);
But now updating main.obj1.data automatically updates main.someArray[0].data and vice versa. I tested it by checking that this is true with console.logs immediately after that line of code. I thought that this command would clone the objects but not make them aliases of the same object. What am I doing wrong?
I have messy code to sort through before this command...is there anything I might have put in my code before that point which would cause $.extend to no longer work like I think it should?
There is two way to solve this
1.
main.obj1.data={};
$.extend(main.obj1.data,main.someArray[0].data);
2.
main.obj1.data=$.extend(true,{},main.someArray[0].data)
Actually both is doing the same thing
You can read more about $.extend()
jQuery extend copy the values so the copied object shouldn't be linked to the initial object. You can verify that in this jsfiddle: http://jsfiddle.net/cFtA7/ (open your console and run the script).
The first parameter in $.extend(true,{},main.someArray[0].data) serve to deep copy your object. If your object has many levels, use this parameter, otherwise, it's not needed.
I'm guessing, but is that possible that your extend code is on a bind object that is called every time you update either one of the values?

Categories