Troubles with testing delete value from object on different browsers - javascript

I need to test deletion from a hash:
store = { 'a': 4 }
delete store['a']
expect(store['a']).toBeUndefined()
this test passed on chrome, but not in firefox. I get:
Expected null not to be defined.
How can I avoid this bug?

You're testing the wrong condition so it doesn't matter if Chrome and Firefox are returning different values (but see below). Consider this:
store = { a: 11 }
store['a'] = undefined
That will give you a store['a'] that is undefined but store will still have 'a' as a key.
If you want to check if delete removes the property, say exactly that:
expect('a' of store).toBe(false)
CoffeeScript's of operator is JavaScript's in operator and from the fine manual:
Using in with deleted or undefined properties
If you delete a property with the delete operator, the in operator returns false for that property.
[...]
If you set a property to undefined but do not delete it, the in operator returns true for that property.
That's exactly the behavior you're trying to test.
For the record, when I say:
store = { 'a': 4 }
delete store['a']
console.log store['a']
I get undefined in the latest Firefox.

Related

property value cannot be undefined in javascript

I am reading a book JavaScript: The Good Parts for increasing my JavaScript knowledge. In Chapter 3 Objects the Author says:
An object is a container of properties, where a property has a name and a value. A property name can be any string, including the empty string. A property value can be any JavaScript value except for undefined.
What does the Author mean by that? As far as I know, we can set values to undefined in an object literal or outside of an object literal using with prototype word. For example Object.prototype.customName = undefined; works well. What am I missing here?
You're right that you can assign the value undefined to a property, and even define a literal with the undefined property; however, the resulting object is very easily confused with the similar object written without that property.
For example, in Node:
> x = {a: 1, b: undefined}
{ a: 1, b: undefined }
> y = {a: 1}
{ a: 1 }
> x.a
1
> y.a
1
> x.b
undefined
> y.b
undefined
> Object.keys(x)
[ 'a', 'b' ]
> Object.keys(y)
[ 'a' ]
> JSON.stringify(x)
'{"a":1}'
> JSON.stringify(y)
'{"a":1}'
It appears the author is saying that if you want to write good, responsible code, you should not use undefined as a property value, because you could asking for confusion.
But semantically, that undefined is really there, so if you interpret what the author is saying literally, it's technically incorrect. But if you follow best practices, I can see what he's trying to get across. It's very Crockford-esque.
By the way, the right way to remove properties is with delete but that's perhaps for a different question.
ADDENDUM
In response to a question in the comments from #prsvr, I looked up the old ECMAScript 3 Specification and found the following:
ECMAScript is object-based: basic language and host facilities are provided by objects, and an ECMAScript program is a cluster of communicating objects. An ECMAScript object is an unordered collection of properties each with zero or more attributes that determine how each property can be used—for example, when the ReadOnly attribute for a property is set to true, any attempt by executed ECMAScript code to change the value of the property has no effect. Properties are containers that hold other objects, primitive values, or methods. A ECMAScript Language primitive value is a member of one of the following built-in types: Undefined, Null, Boolean, Number, and String; an object is a member of one of the following built-in types: Undefined, Null, Boolean, Number, and String; an object is a member of the remaining built-in type Object; and a method is a function associated with an object via a property.
There is no mention of undefined being disallowed as property values in the spec. (https://www-archive.mozilla.org/js/language/E262-3.pdf).
There were changes to undefined during the evolution of JavaScript; for example you used to be able to reassign the value of the identifier undefined to some value other than undefined, hence the idiom typeof(x) === "undefined" (among others).
I think the author is trying to say that a key of an object cannot be defined without defining its value. That is, a key should always have a value.
For example if the key test is defined without defining its value, it will throw an error.
var abc = {
test:
}
i think because js object consider undefined is default value for both inactive key and unknown key
var person = {
name: 'name',
'': 'this is empty key',
null: 'this is null key',
another_null: null,
undefined: 'this is undefined key',
inactive_key: undefined
}
console.log(person['key_from_nowhere']) // unknown key => undefined
console.log(person.hasOwnProperty('key_from_nowhere')) // false
console.log(person['inactive_key']) // undefined
console.log(person.hasOwnProperty('inactive_key')) // true
so that if you assign value of a object's key to undefined then this key fall into the inactive key case (JSON.stringify will ignore)
person.name = undefined;
console.log(JSON.stringify(person)); // name will disappear
BTW, i see that assign undefined maybe cause confuse and error prone since logic code must use hasOwnProperty to check the key exist or not, so do you think that the best practice here is do not assign undefined ?

javascript window.document in the console [duplicate]

In Chrome the console object defines two methods that seem to do the same thing:
console.log(...)
console.dir(...)
I read somewhere online that dir takes a copy of the object before logging it, whereas log just passes the reference to the console, meaning that by the time you go to inspect the object you logged, it may have changed. However some preliminary testing suggests that there's no difference and that they both suffer from potentially showing objects in different states than when they were logged.
Try this in the Chrome console (Ctrl+Shift+J) to see what I mean:
> o = { foo: 1 }
> console.log(o)
> o.foo = 2
Now, expand the [Object] beneath the log statement and notice that it shows foo with a value of 2. The same is true if you repeat the experiment using dir instead of log.
My question is, why do these two seemingly identical functions exist on console?
In Firefox, these function behave quite differently: log only prints out a toString representation, whereas dir prints out a navigable tree.
In Chrome, log already prints out a tree -- most of the time. However, Chrome's log still stringifies certain classes of objects, even if they have properties. Perhaps the clearest example of a difference is a regular expression:
> console.log(/foo/);
/foo/
> console.dir(/foo/);
* /foo/
global: false
ignoreCase: false
lastIndex: 0
...
You can also see a clear difference with arrays (e.g., console.dir([1,2,3])) which are logged differently from normal objects:
> console.log([1,2,3])
[1, 2, 3]
> console.dir([1,2,3])
* Array[3]
0: 1
1: 2
2: 3
length: 3
* __proto__: Array[0]
concat: function concat() { [native code] }
constructor: function Array() { [native code] }
entries: function entries() { [native code] }
...
DOM objects also exhibit differing behavior, as noted on another answer.
Another useful difference in Chrome exists when sending DOM elements to the console.
Notice:
console.log prints the element in an HTML-like tree
console.dir prints the element in a JSON-like tree
Specifically, console.log gives special treatment to DOM elements, whereas console.dir does not. This is often useful when trying to see the full representation of the DOM JS object.
There's more information in the Chrome Console API reference about this and other functions.
None of the 7 prior answers mentioned that console.dir supports extra arguments: depth, showHidden, and whether to use colors.
Of particular interest is depth, which (in theory) allows travering objects into more than the default 2 levels that console.log supports.
I wrote "in theory" because in practice when I had a Mongoose object and ran console.log(mongoose) and console.dir(mongoose, { depth: null }), the output was the same. What actually recursed deeply into the mongoose object was using util.inspect:
import * as util from 'util';
console.log(util.inspect(myObject, {showHidden: false, depth: null}));
I think Firebug does it differently than Chrome's dev tools. It looks like Firebug gives you a stringified version of the object while console.dir gives you an expandable object. Both give you the expandable object in Chrome, and I think that's where the confusion might come from. Or it's just a bug in Chrome.
In Chrome, both do the same thing. Expanding on your test, I have noticed that Chrome gets the current value of the object when you expand it.
> o = { foo: 1 }
> console.log(o)
Expand now, o.foo = 1
> o.foo = 2
o.foo is still displayed as 1 from previous lines
> o = { foo: 1 }
> console.log(o)
> o.foo = 2
Expand now, o.foo = 2
You can use the following to get a stringified version of an object if that's what you want to see. This will show you what the object is at the time this line is called, not when you expand it.
console.log(JSON.stringify(o));
Use console.dir() to output a browse-able object you can click through instead of the .toString() version, like this:
console.dir(obj/this/anything)
How to show full object in Chrome console?
From the firebug site
http://getfirebug.com/logging/
Calling console.dir(object) will log an interactive listing of an object's properties, like > a miniature version of the DOM tab.
Following Felix Klings advice I tried it out in my chrome browser.
console.dir([1,2]) gives the following output:
Array[2]
0: 1
1: 2
length: 2
__proto__: Array[0]
While console.log([1,2]) gives the following output:
[1, 2]
So I believe console.dir() should be used to get more information like prototype etc in arrays and objects.
Difference between console.log() and console.dir():
Here is the difference in a nutshell:
console.log(input): The browser logs in a nicely formatted manner
console.dir(input): The browser logs just the object with all its properties
Example:
The following code:
let obj = {a: 1, b: 2};
let DOMel = document.getElementById('foo');
let arr = [1,2,3];
console.log(DOMel);
console.dir(DOMel);
console.log(obj);
console.dir(obj);
console.log(arr);
console.dir(arr);
Logs the following in google dev tools:
Well, the Console Standard (as of commit ef88ec7a39fdfe79481d7d8f2159e4a323e89648) currently calls for console.dir to apply generic JavaScript object formatting before passing it to Printer (a spec-level operation), but for a single-argument console.log call, the spec ends up passing the JavaScript object directly to Printer.
Since the spec actually leaves almost everything about the Printer operation to the implementation, it's left to their discretion what type of formatting to use for console.log().

Is there a way to get console.table to execute property accessor functions?

I have a collection of objects with many getter properties. I'd like to be able to print a subset of these values in the console using console.table. The current implementations do not seem to allow this, is there a workaround?
let obj = {
get prop() {
return "getter";
}
id:1
}
console.table([obj]); // prints only index, and id
console.table([obj], ["prop"]); // prints only index, but still not "prop"
The console.table api is still non-standard.
Currently - chrome is not capable of working with getters values, and if you will check firefox - all values that are defined by getters are printed as undefined.
Note that this has nothing to do with hasOwnProperty or 'prop' in obj (both works great), however it might be related to Object.getOwnPropertyDescriptor.
In your example (for both Chrome & Firefox):
Object.getOwnPropertyDescriptor(obj, 'id').value
// 1
Object.getOwnPropertyDescriptor(obj, 'prop').value
// undefined
However if this is the case I would expect from Chrome to also display the prop column (even with the undefined values in it).
You can use this snippet to test on your browser:
let obj = {
get prop() {
return "getter";
},
id:1
}
console.log('Log "t in obj"')
for (var t in obj) {
console.log(t, obj[t]);
}
console.log('')
console.table([obj]);
console.table([obj], ["id"]);
console.table([obj], ["prop"]); // currently returns a column of 'undefined' in firefox, and in chrome that column doesn't exists.

Javascript "Cannot read property 'length' of undefined" when checking a variable's length

I'm building a node scraper that uses cheerio to parse the DOM. This is more or a vanilla javascript question though. At one part of my scrape, I'm loading some content into a variable, then checking the variable's length, like so:
var theHref = $(obj.mainImg_select).attr('href');
if (theHref.length){
// do stuff
} else {
// do other stuff
}
This works just fine, until I came across a url for which $(obj.mainImg_select).attr('href') didn't exist. I assumed that my theHref.length check would account for this and skip through to the else: do other stuff statement, but instead I got:
TypeError: Cannot read property 'length' of undefined
What am I doing wrong here and how can I fix this?
You can check that theHref is defined by checking against undefined.
if (undefined !== theHref && theHref.length) {
// `theHref` is not undefined and has truthy property _length_
// do stuff
} else {
// do other stuff
}
If you want to also protect yourself against falsey values like null then check theHref is truthy, which is a little shorter
if (theHref && theHref.length) {
// `theHref` is truthy and has truthy property _length_
}
Why?
You asked why it happens, let's see:
The official language specificaion dictates a call to the internal [[GetValue]] method. Your .attr returns undefined and you're trying to access its length.
If Type(V) is not Reference, return V.
This is true, since undefined is not a reference (alongside null, number, string and boolean)
Let base be the result of calling GetBase(V).
This gets the undefined part of myVar.length .
If IsUnresolvableReference(V), throw a ReferenceError exception.
This is not true, since it is resolvable and it resolves to undefined.
If IsPropertyReference(V), then
This happens since it's a property reference with the . syntax.
Now it tries to convert undefined to a function which results in a TypeError.
There's a difference between an empty string "" and an undefined variable. You should be checking whether or not theHref contains a defined string, rather than its lenght:
if(theHref){
// ---
}
If you still want to check for the length, then do this:
if(theHref && theHref.length){
// ...
}
In addition to others' proposals, there is another option to handle that issue.
If your application should behave the same in case of lack of "href" attribute, as in case of it being empty, just replace this:
var theHref = $(obj.mainImg_select).attr('href');
with this:
var theHref = $(obj.mainImg_select).attr('href') || '';
which will treat empty string ('') as the default, if the attribute has not been found.
But it really depends, on how you want to handle undefined "href" attribute. This answer assumes you will want to handle it as if it was empty string.
If you aren't doing some kind of numeric comparison of the length property, it's better not to use it in the if statement, just do:
if(theHref){
// do stuff
}else{
// do other stuff
}
An empty (or undefined, as it is in this case) string will evaluate to false (just like a length of zero would.)
As has been discussed elsewhere, the .length property reference is failing because theHref is undefined. However, be aware of any solution which involves comparing theHref to undefined, which is not a keyword in JavaScript and can be redefined.
For a full discussion of checking for undefined variables, see Detecting an undefined object property and the first answer in particular.
You can simply check whether the element length is undefined or not just by using
var theHref = $(obj.mainImg_select).attr('href');
if (theHref){
//get the length here if the element is not undefined
elementLength = theHref.length
// do stuff
} else {
// do other stuff
}

What reason is there to use null instead of undefined in JavaScript?

I've been writing JavaScript for quite a long time now, and I have never had a reason to use null. It seems that undefined is always preferable and serves the same purpose programmatically. What are some practical reasons to use null instead of undefined?
I don't really have an answer, but according to Nicholas C. Zakas, page 30 of his book "Professional JavaScript for Web Developers":
When defining a variable that is meant
to later hold an object, it is
advisable to initialize the variable
to null as opposed to anything else.
That way, you can explicitly check for the value null to determine if
the variable has been filled with an object reference at a later time
At the end of the day, because both null and undefined coerce to the same value (Boolean(undefined) === false && Boolean(null) === false), you can technically use either to get the job done. However, there is right way, IMO.
Leave the usage of undefined to the JavaScript compiler.
undefined is used to describe variables that do not point to a reference. It is something that the JS compiler will take care for you. At compile time the JS engine will set the value of all hoisted variables to undefined. As the engine steps through the code and values becomes available the engine will assign respective values to respective variables. For those variables for whom it did not find values, the variables would continue to maintain a reference to the primitive undefined.
Only use null if you explicitly want to denote the value of a variable as having "no value".
As #com2gz states: null is used to define something programmatically empty. undefined is meant to say that the reference is not existing. A null value has a defined reference to "nothing". If you are calling a non-existing property of an object, then you will get undefined. If I would make that property intentionally empty, then it must be null so you know that it's on purpose.
TLDR; Don't use the undefined primitive. It's a value that the JS compiler will automatically set for you when you declare variables without assignment or if you try to access properties of objects for which there is no reference. On the other hand, use null if and only if you intentionally want a variable to have "no value".
Sidebar: I, personally, avoid explicitly setting anything to undefined (and I haven't come across such a pattern in the many codebases/third party libs I've interacted with). Also, I rarely use null. The only times I use null is when I want to denote the value of an argument to a function as having no value, i.e.,:
function printArguments(a,b) {
console.log(a,b);
}
printArguments(null, " hello") // logs: null hello
null and undefined are essentially two different values that mean the same thing. The only difference is in the conventions of how you use them in your system. As some have mentioned, some people use null for meaning "no object" where you might sometimes get an object while undefined means that no object was expected (or that there was an error). My problem with that is its completely arbitrary, and totally unnecessary.
That said, there is one major difference - variables that aren't initialized (including function parameters where no argument was passed, among other things) are always undefined.
Which is why in my code I never use null unless something I don't control returns null (regex matching for example). The beauty of this is it simplifies things a lot. I never have to check if x === undefined || x === null, I can just check x === undefined. And if you're in the habit of using == or simply stuff like if(x) ... , stop it.
!x will evaluate to true for an empty string, 0, null, NaN - i.e. things you probably don't want. If you want to write javascript that isn't awful, always use triple equals === and never use null (use undefined instead). It'll make your life way easier.
undefined is where no notion of the thing exists; it has no type, and it's never been referenced before in that scope; null is where the thing is known to exist, but it has no value.
Everyone has their own way of coding and their own internal semantics, but over the years I have found this to be the most intuitive advice that I give people who ask this question: when in doubt, do what JavaScript does.
Let's say you are working with object properties like options for a jQuery plugin...ask yourself what value JavaScript gives a property that has yet to be defined -- the answer is undefined. So in this context, I would initialize these types of things with 'undefined' to be consistent with JavaScript (for variables, you can do var myVar; instead of var myVar = undefined;).
Now let's say you are doing DOM manipulation...what value does JavaScript assign to non-existent elements? The answer is null. This is the value I would initialize with if you are creating a placeholder variable that will later hold a reference to an element, document fragment, or similar that relates to the DOM.
If you're working with JSON, then a special case needs to be made: for undefined property values, you should either set them to "" or null because a value of undefined is not considered proper JSON format.
With this said, as a previous poster has expressed, if you find that you're initializing stuff with null or undefined more than once in a blue moon, then maybe you should reconsider how you go about coding your app.
You might adopt the convention suggested here, but there really is no good reason to. It is not used consistently enough to be meaningful.
In order to make the convention useful, you first must know that the called function follows the convention. Then you have to explicitly test the returned value and decide what to do. If you get undefined, you can assume that some kind of error occurred that the called function knew about. But if an error happened, and the function knew about it, and it is useful to send that out into the wider environment, why not use an error object? i.e. throw an error?
So at the end of the day, the convention is practically useless in anything other than very small programs in simple environments.
A few have said that it is ok to initialise objects to null. I just wanted to point out that destructuring argument defaults don't work with null. For example:
const test = ({ name } = {}) => {
console.log(name)
}
test() // logs undefined
test(null) // throws error
This requires performing null checks prior to calling the function which may happen often.
A useful property in null that undefined does not qualifies:
> null + 3
3
> undefined + 3
NaN
I use null when I want to 'turn off' a numeric value,
or to initialize some. My last use was manipulating css transform:
const transforms = { perspective : null, rotateX : null };
// if already set, increase, if not, set to x
runTimeFunction((x) => { trasforms.perspective += x; });
// still useful, as setting perspective to 0 is different than turning it off
runTimeFunction2((x) => { transforms.perspective = null; });
// toCss will check for 'null' values and not set then at all
runTimeFunction3(() => { el.style.transform = toCss(transforms); });
Not sure if I should use this property thought...
DOM nodes and elements are not undefined, but may be null.
The nextSibling of the last child of an element is null.
The previousSibling of the first child is null.
A document.getElementById reference is null if the element does not exist in the document.
But in none of these cases is the value undefined; there just is no node there.
Unknown variable: undefined.
Known variable yet no value: null.
You receive an object from a server, server_object.
You reference server_object.errj. It tells you it’s undefined. That means it doesn’t know what that is.
Now you reference server_object.err. It tells you it’s null. That means you’re referencing a correct variable but it’s empty; therefore no error.
The problem is when you declare a variable name without a value (var hello) js declares that as undefined: this variable doesn’t exist; whereas programmers mostly mean: “I’ve not given it a value yet”, the definition of null.
So the default behavior of a programmer—declaring a variable without a value as nothing—is at odds with js—declaring it as not existing. And besides, !undefined and !null are both true so most programmers treat them as equivalent.
You could of course ensure you always do var hello = null but most won’t litter their code as such to ensure type sanity in a deliberately loosely-typed language, when they and the ! operator treat both undefined and null as equivalent.
In JavaScript, the value null represents the intentional absence of any object value. null expresses a lack of identification, indicating that a variable points to no object.
The global undefined property represents the primitive value undefined.
undefined is a primitive value automatically assigned to variables.
undefined is meant to say that the reference is not existing.
I completely disagree that usage null or undefined is unnecessary.
undefined is thing which keeping alive whole prototype chaining process.
So compiler only with null can't check if this property just equal to null, or its not defined in endpoint prototype. In other dynamic typed languages(f.e. Python) it throws exception if you want access to not defined property, but for prototype-based languages compiler should also check parent prototypes and here are the place when undefined need most.
Whole meaning of using null is just bind variable or property with object which is singleton and have meaning of emptiness,and also null usage have performance purposes. This 2 code have difference execution time.
var p1 = function(){this.value = 1};
var big_array = new Array(100000000).fill(1).map((x, index)=>{
p = new p1();
if(index > 50000000){
p.x = "some_string";
}
return p;
});
big_array.reduce((sum, p)=> sum + p.value, 0)
var p2 = function(){this.value = 1, p.x = null};
var big_array = new Array(100000000).fill(1).map((x, index)=>{
p = new p2();
if(index > 50000000){
p.x = "some_string";
}
return p;
});
big_array.reduce((sum, p)=> sum + p.value, 0)
I'm working through this exact question right now, and looking at the following philosophy:
Any function that is intended to return a result should return null if it fails to find a result
Any function that is NOT intended to return a result implicitly returns undefined.
For me, this question is significant because anyone calling a function that returns a result should have no question as to whether to test for undefined vs null.
This answer does not attempt to address:
Property values of null vs undefined
Variables within your functions being null vs undefined
In my opinion, variables are your own business and not a part of your API, and properties in any OO system are defined and therefore should be defined with value different from what they would be if not defined (null for defined, undefined is what you get when accessing something that is not in your object).
Here's a reason: var undefined = 1 is legal javascript, but var null = 1 is a syntax error. The difference is that null is a language keyword, while undefined is, for some reason, not.
If your code relies on comparisons to undefined as if it's a keyword (if (foo == undefined) -- a very easy mistake to make) that only works because nobody has defined a variable with that name. All that code is vulnerable to someone accidentally or maliciously defining a global variable with that name. Of course, we all know that accidentally defining a global variable is totally impossible in javascript...
Just wanna add that with usage of certain javascript libraries, null and undefined can have unintended consequences.
For example, lodash's get function, which accepts a default value as a 3rd argument:
const user = {
address: {
block: null,
unit: undefined,
}
}
console.log(_.get(user, 'address.block', 'Default Value')) // prints null
console.log(_.get(user, 'address.unit', 'Default Value')) // prints 'Default Value'
console.log(_.get(user, 'address.postalCode', 'Default Value')) // prints 'Default Value'
Another example: If you use defaultProps in React, if a property is passed null, default props are not used because null is interpreted as a defined value.
e.g.
class MyComponent extends React.Component {
static defaultProps = {
callback: () => {console.log('COMPONENT MOUNTED')},
}
componentDidMount() {
this.props.callback();
}
}
//in some other component
<MyComponent /> // Console WILL print "COMPONENT MOUNTED"
<MyComponent callback={null}/> // Console will NOT print "COMPONENT MOUNTED"
<MyComponent callback={undefined}/> // Console WILL print "COMPONENT MOUNTED"
There are already some good answers here but not the one that I was looking for. null and undefined both "technically" do the same thing in terms of both being falsy, but when I read through code and I see a "null" then I'm expecting that it's a user defined null, something was explicitly set to contain no value, if I read through code and see "undefined" then I assume that it's code that was never initialized or assigned by anything. In this way code can communicate to you whether something was caused by uninitialized stuff or null values. Because of that you really shouldn't assign "undefined" manually to something otherwise it messes with the way you (or another developer) can read code. If another developer sees "undefined" they're not going to intuitively assume it's you who made it undefined, they're going to assume it's not been initialized when in fact it was. For me this is the biggest deal, when I read code I want to see what it's telling me, I don't want to guess and figure out if stuff has "actually" been initialized.
Not even to mention that using them in typescript means two different things. Using:
interface Example {
name?: string
}
Means that name can be undefined or a string, but it can't be null. If you want it null you have to explicitly use:
interface Example {
name: string | null
}
And even then you'll be forced to initialize it at least with "null".
That's of course only true if you're using "strictNullChecks": true in tsconfig.json.
Based on a recent breakage we ran into, the example below shows why I prefer to use undefined over null, unless there is a specific reason to do otherwise:
function myfunc (myArg) {
if (typeof myArg === 'string') {
console.log('a', myArg);
} else if (typeof abc === 'object') {
console.log('b', myArg);
if (myArg.id) {
console.log('myArg has an id');
} else {
console.log('myArg has an id');
}
} else {
console.log('no value');
}
}
The following values will play nicely:
'abc'
{}
undefined
{ id: 'xyz' }
On the other hand the assumption of null and undefined being equivalent here breaks the code. The reason being is that null is of type of object, where as undefined is of type undefined. So here the code breaks because you can't test for a member on null.
I have seen a large number of cases with code of similar appearance, where null is just asking for problems:
if (typeof myvar === 'string') {
console.log(myvar);
} else if (typeof myvar === 'object') {
console.log(myvar.id);
}
The fix here would be to explicitly test for null:
if (typeof myvar === 'string') {
console.log(myvar);
} else if (myvar !== null && typeof myvar === 'object') {
console.log(myvar.id);
}
My attitude is to code for the weaknesses of a language and the typical behaviours of programmers of that language, hence the philosophy here of going with 'undefined' bey default.
To write simple code you need to keep complexity and variation down. When a variable or a property on an object does not have a value it is undefined , and for a value to be null you need to assign it a null value.
Undeclared vs Null
null is both an Object "type" and one of the 7 unique primitive value types called null
undefined is both a global scope property and type called undefined and one of the 7 unique primitive value types called undefined (window.undefined) .
It is the primitive types we use as values we are interested in.
In the case of null, as a value type it means an empty value has been assigned to a variable, but the variable type (Number, String, etc) is still defined. It just has no value. That is what null means. It means a variable has an empty value but it is still a value. It also reinitializes the variable with some kind of value, but is not undefined as a type.
undefined is a special case. When you declare a variable (or use a missing value not yet declared) it is of type undefined, as the browser does not know what type of data has been assigned to it yet. If the variable is declared but not assigned a value is is assigned the primitive calue undefined by default prior to assigning a value, and implies the variable does not exist or exists but has no value assigned.
Like null, undefined is also a primitive value type. But unlike null it means the variable does not exist, where null means the value does not exist. That is why its always better to check if the variable exists and has been assigned a variable using undefined before checking if the value is null or empty. undefined implies no variable or object exists in the compilation at all. The variable has either not been declared or declared with a missing value so not initialized. So checking for undefined is a very good way to avoid many types of errors in JavaScript and supersedes null.
That is why I would not rely on "truthy" checks for true/false with null and undefined, even though they will both return a false response, as undefined implies an additional step for missing feature, object, or variable, not just a true/false check. It implies something more. If you have a missing undeclared variable, truthy statements will trigger an ERROR!
Let's look at undefined first:
//var check1;// variable doesnt even exist so not assigned to "undefined"
var check2;// variable declared but not initialized so assigned "undefined"
var check3 = 'hello world';// variable has a value so not undefined
console.log('What is undefined?');
//console.log(check1 === undefined);// ERROR! check1 does not exist yet so not assigned undefined!
console.log(check2 === undefined);// True
console.log(check3 === undefined);// False
console.log(typeof check1 === 'undefined');// True - stops the ERROR!
console.log(typeof check2 === 'undefined');// True
console.log(typeof check3 === 'undefined');// False
As you can see undeclared variables, or declared but not initialized, both are assigned a type of undefined. Notice declared variables that are not initialized are assigned a value of undefined, the primitive value type but variables that do not exist are undefined types.
null has nothing to do with missing variables or variables not yet assigned values, as null is still a value. So anything with a null is already declared and initialized. Also notice a variable assigned a null value is actually an object type unlike undefined types. For example...
var check4 = null;
var check5 = 'hello world';
console.log('What is null?');
console.log(check4 === undefined);// False
console.log(check5 === undefined);// False
console.log(typeof check4 === 'undefined');// False
console.log(typeof check5 === 'undefined');// False
console.log(typeof check4);// return 'object'
console.log(typeof check5);// return 'string'
As you can see each act differently and yet both are primitive values you can assign any variable. Just understand they represent different states of variables and objects.

Categories

Resources