browser-inconsistent unexpected "undefined" string when using object destruction - javascript

When I am trying out some object destruction syntax in some browser consoles, something unexpected happened.
Firstly I entered
action = {
type: "SET_APPS_UI_REVERT",
device: 23456,
managedApps: "12345"
}
and then
( { type, status, appsInfo, device,managedApps,appName } = action);
lastly
status
So both chrome and firefox decided to give me an "undefined" that is a string, rather than a undefined value, while edge would give me an usual undefined. However, when I typed
const { type, status, appsInfo, device,managedApps,appName } = action
and then
status
in edge, it gives me a "" rather than undefined.
Is this results of some browser inconsistency? Or actually some bugs?
Screenshots are below
chrome-66-0-3359-181-no-const.PNG
edge-41-16299-402-0-with-edgehtml-16-16299-no-const.PNG
edge-41-16299-402-0-with-edgehtml-16-16299-with-const.PNG
firefox-60-0-1-no-const.PNG

Using the following syntax:
( { type, status, appsInfo, device,managedApps,appName } = action);
You are explicitly saying "destructure action.status to the existing variable status.
If you don't already have a variable called status in the local scope then it will attempt to assign action.status to the window.status property. This property only accepts a string, so when action does not have a status property, you've effectively done this:
window.status = undefined;
Since window.status coerces to a string, when this is read back you get window.status === "undefined";.
Even though this doesn't have any effect on the statusbar in Firefox, it still exhibits the behaviour.
Your second part is expected behaviour also:
const { type, status, appsInfo, device,managedApps,appName } = action
Is different from before because you're declaring a scoped variable called status. This is where the browser differences come in. In Chrome, when you declare const status in devtools, the devtools is considered the "scope" and you can access it after it's declared. In Edge however, you can declare const within Dev Tools, but you can never access the value. Reference.
So in Edge, you get this kind of behaviour:
{
const status = action.status;
typeof status === "undefined"; // true
}
status; // The value of window.status. const status is out of scope

Related

Using string key to access Firestore map value gives IDE warning that string was never read

I have a Firebase Cloud Function that reads a document from Firestore, gets a map field, and gets a boolean value from one of that map's keys. However, my IDE says that the string key I use to get the value from the map (someKey in the code below) is "declared but never read", which puzzles me. Aren't I reading it when I use it to access the map? What am I doing wrong?
exports.someFunction = functions.https.onCall(async (data, _context) => {
const uid = data.uid;
const someKey = data.someKey; // function argument; guaranteed to be a string
const settingsDoc = await admin.firestore().doc("settings/" + uid).get();
const theMapInQuestion = settingsDoc.get("theMapInQuestion"); // guaranteed to be a Firestore map of type [string: boolean]
const theBooleanInQuestion = theMapInQuestion.someKey;
if (theBooleanInQuestion === true) {
// proceed
} else {
...
}
});
The message is telling you that you never used the const someKey after it was declared. Indeed, I do not see where that variable is ever used in the code you show here. You could certainly delete the line of code that declares someKey and it would work exactly the same.
The only thing you're doing wrong that I can see is assuming that the const is actually being used when the compiler says it's not. (It's rarely a good idea to doubt the compiler.)
If you intended to access the property with the value of the someKey variable, then you meant to write theMapInQuestion[someKey].

VUEX, what to do when $store.state is null

When users are not logged into my website, the state of user is set to null.
However, this throws up a lot of issues on some pages where i look to see if this.$store.user
For example, if I were to have a simple check such as
if (this.$store.getters.userInfo.likedProjects.includes(title)) {this.hasLiked = true}
and the user is not logged in (thus, setting the state of user to null by default) I get this error;
_this.$store.getters.userInfo is null
How should I correctly handle this sort of issues so that my console does not get flooded with typescript errors?
My initial idea was to first check if user.loggedIn == true and wrap everything inside of that, but that seems awfully messy just to avoid some errors...
Use optional chaining, which is available in TypeScript 3.7+:
if (this.$store.getters.userInfo?.likedProjects.includes(title)) {
this.hasLiked = true;
}
If userInfo is null or undefined, then the entire statement this.$store.getters.userInfo?.likedProjects.includes(title) will return undefined instead of throwing an error.
If likedProjects may also be null or undefined, then you need to use optional chaining on that property too, i.e.:
if (this.$store.getters.userInfo?.likedProjects?.includes(title)) {
this.hasLiked = true;
}
if(this.$store.getters.userInfo){
if (this.$store.getters.userInfo.likedProjects.includes(title)) {this.hasLiked = true}
}

cannot read property 'push' of null

I have a page which works on my localhost.. when I put t on a remote server, it gave an error. the code which returns the error is
var $app_list = localStorage.getItem('LsAppList');
var AppListJson = JSON.parse($app_list);
AppListJson.push({
"extapp_id": appdetail.get("addAppId"),
"desc": appdetail.get("addAppName"),
"device_no": appdetail.get("devicenoValue"),
"validation_key": appdetail.get("activationkeyValue")
});
the console log is
Uncaught TypeError: Cannot read property 'push' of null
addToJson EncigoHome.js:126
n.extend.trigger kendo.mobile.min.js:9
s.extend._release kendo.mobile.min.js:15
i._userEvents.o.UserEvents.tap kendo.mobile.min.js:15
n.extend.trigger kendo.mobile.min.js:9
l.extend.notify kendo.mobile.min.js:13
u.extend._trigger kendo.mobile.min.js:13
u.extend.end kendo.mobile.min.js:13
l.extend._eachTouch kendo.mobile.min.js:13
l.extend._end kendo.mobile.min.js:13
arguments.length.t.(anonymous function) kendo.mobile.min.js:10
b.event.dispatch jquery-1.9.1.js:9593
v.handle
localStorage is per domain (more specifically same origin). The localStorage associated with the remote domain does not have access to the values stored in the localStorage associated with your localhost.
You should check to see if there is a stored value and fallback to a default one or treat the error:
var $app_list = localStorage.getItem('LsAppList');
var AppListJson = $app_list != null ? JSON.parse($app_list) : [];
//...
More verbose:
var $app_list = localStorage.getItem('LsAppList'),
AppListJson;
if ($app_list != null) {
AppListJson = JSON.parse($app_list);
} else {
// treat no LsAppList stored case
// you could show a message or set it to a default value
AppListJson = [];
}
This "no previously stored data" scenario will happen whenever the user clears his browser data or switches browsers/devices as well, so it must be treated properly.
The root cause of the error, as you've probably figured out already, is that localStorage.getItem(key) returns null when no value is stored for the given key in the current domain. Then JSON.parse(null) === null and null.push() throws.
Just as a nitpick, I'd suggest reviewing your variables naming:
Don't use PascalCase naming for non-constructors.
Don't mix camelCase with underline naming conventions.
Recommended read: Idiomatic.js naming.
And also, AppListJson is not JSON, it is a native array. JSON can only exist in string context, that is, your $app_list is JSON. More in-depth explanation about JSON/not JSON: There's no such thing as a "JSON Object"
The .push() method can only be used on arrays.
It seems that you don't have the item stored in localStorage, which is why it is returning null

Typescript variable "does not appear in current scope"

I am trying to use the following code:
$('body').bind('ajaxSend', function (elm, xhr, s) {
if (s.hasContent && securityToken) { // handle all verbs with content
var tokenParam = "__RequestVerificationToken=" + encodeURIComponent(securityToken);
s.data = s.data ? [s.data, tokenParam].join("&") : tokenParam;
// ensure Content-Type header is present!
if (s.contentType !== false || options.contentType) {
xhr.setRequestHeader( "Content-Type", s.contentType);
}
}
});
I found this in the post Stack Overflow post
With typescript I get a syntax error on "options" saying "the name options does not appear in the current scope.
Can someone help and explain why I am getting this error. I see options is not declared and wonder where it comes from if it's not declared.
It's just like with JavaScript where, at run-time, any enclosing function scopes and then the global scope are searched for an options variable and if it isn't found anywhere an exception is thrown because it's not defined.
So presumably, in the example code you pulled this from, you should assume that options is defined elsewhere, and you'd need to do the same.
I believe the slight mistake is that this line:
if (s.contentType !== false || options.contentType) {
Should actually be:
if (s.contentType !== false || s.contentType) {
As your parameter s is the ajaxOptions passed to your function by jQuery.

Having IE Issues When Passing Object By Ref. and Dynamically Adding Properties

So, I've created a function to do some error checking on an XML file that I recieve from an AJAX call. Part of the validation is that the function then builds out an object for easy access while I process that data into a form. In FF, works like a charm. IE dies with the error:
Object doesn't support this property or method
Here is the function (minus the un-important bits):
function checkReceiveXMLTagString( doc, messageObject, tag ) {
var tag_nodes = doc.getElementsByTagName( tag );
...do some error checking...
messageObject[tag] = tag_str; <-- error occurs on this line
return true;
}
Here is an example of how the function is call:
if ( checkReceiveXMLTagString( messageObject.Name[0], messageObject.Name[0], "First" ) ) {
...process messageObject.Name[0].First...
}
Like I said, FF has no issues. Safari loads the pages as well. IE has issues.
Thanks!
Looks like something is making messageObject be null or undefined
If the error is on this line:
messageObject[tag] = tag_str;
Then, the only two ways I know of that that can cause an error are:
messageObject is not an object that you can set properties on (null or undefined are the most likely ways that would happen)
tag is null or undefined
Since I see that your code calls this function hundreds of times so you can't effectively just break on it, I'd suggest you put in some defensive coding to check for those conditions and output something to the debug console to identify what the state is when the problem occurs. You can even trigger a conditional breakpoint with code like this:
if (!messageObject || !tag) {
debugger;
}
In the toughest cases, you can put an exception handler around it and break when the exception is thrown:
try {
messageObject[tag] = tag_str;
} catch(e) {
debugger;
}
Both of these will allow you to capture the condition in the debugger and examine all your parameters at the time of the error.

Categories