Typeerror Cannot Read Property 'length' of Undefined Javascript
Nearly of the modern languages like Ruby, Python, or Java accept a single nil value (nil
or null
), which seems a reasonable approach.
But JavaScript is different.
null
, but also undefined
, represent in JavaScript empty values. So what'due south the exact difference between them?
The curt respond is that JavaScript interpreter returns undefined
when accessing a variable or object property that is not all the same initialized. For instance:
javascript
let company ;
company ; // => undefined
let person = { name: 'John Smith' };
person . age ; // => undefined
On the other side, null
represents a missing object reference. JavaScript doesn't initialize variables or object properties with null
.
Some native methods similar String.prototype.friction match()
can return cipher
to denote a missing object. Take a look at the sample:
javascript
let array = null ;
array ; // => null
let movie = { proper noun: 'Starship Troopers' , musicBy: nil };
movie . musicBy ; // => nada
'abc' . match ( / [ 0-9 ] / ); // => nothing
Because JavaScript is permissive, developers have the temptation to access uninitialized values. I'one thousand guilty of such bad practise too.
Ofttimes such risky actions generate undefined
related errors:
-
TypeError: 'undefined' is not a function
-
TypeError: Cannot read property '<prop-name>' of undefined
- and alike blazon errors.
JavaScript developer can sympathise the irony of this joke:
javascript
function undefined () {
// problem solved
}
To reduce such errors, you have to empathise the cases when undefined
is generated. Permit'south explore undefined
and its upshot on code safety.
Tabular array of Contents
- one. What is undefined
- 2. Scenarios that create undefined
- two.1 Uninitialized variable
- ii.2 Accessing a non-existing holding
- ii.three Function parameters
- two.iv Function render value
- 2.5 void operator
- 3. undefined in arrays
- four. Divergence between undefined and null
- 5. Conclusion
1. What is undefined
JavaScript has six primitive types:
- Boolean:
true
orfalse
- Number:
ane
,half dozen.7
,0xFF
- String:
"Gorilla and assistant"
- Symbol:
Symbol("name")
(starting ES2015) - Null:
null
- Undefined:
undefined
.
And a separated object type: {name: "Dmitri"}
, ["apple", "orange"]
.
From half dozen primitive types undefined
is a special value with its own type Undefined. According to ECMAScript specification:
Undefined value primitive value is used when a variable has not been assigned a value.
The standard clearly defines that you volition receive undefined
when accessing uninitialized variables, not-existing object properties, non-existing array elements, and alike.
A few examples:
javascript
let number ;
number ; // => undefined
let motion picture = { name: 'Interstellar' };
moving-picture show . twelvemonth ; // => undefined
let movies = [ 'Interstellar' , 'Alexander' ];
movies [ iii ]; // => undefined
The to a higher place case demonstrates that accessing:
- an uninitialized variable
number
- a non-existing object property
movie.year
- or a non-existing array element
movies[3]
are evaluated to undefined
.
The ECMAScript specification defines the type of undefined
value:
Undefined type is a type whose sole value is the
undefined
value.
In this sense, typeof
operator returns 'undefined'
string for an undefined
value:
javascript
typeof undefined === 'undefined' ; // => truthful
Of course typeof
works nicely to verify whether a variable contains an undefined
value:
javascript
let naught ;
typeof cipher === 'undefined' ; // => true
two. Scenarios that create undefined
two.1 Uninitialized variable
A declared variable but not withal assigned with a value (uninitialized) is by default
undefined
.
Plain and uncomplicated:
javascript
allow myVariable ;
myVariable ; // => undefined
myVariable
is alleged and not yet assigned with a value. Accessing the variable evaluates to undefined
.
An efficient approach to solve the troubles of uninitialized variables is whenever possible assign an initial value. The less the variable exists in an uninitialized land, the better.
Ideally, you would assign a value right away after declaration const myVariable = 'Initial value'
. Just that's not e'er possible.
Tip 1: Favor const
, otherwise apply permit
, only say goodbye to var
In my stance, one of the all-time features of ECMAScript 2022 is the new style to declare variables using const
and permit
. It is a big pace forward.
const
and permit
are block scoped (contrary to older function scoped var
) and exist in a temporal dead zone until the announcement line.
I recommend const
variable when its value is not going to change. Information technology creates an immutable binding.
1 of the nice features of const
is that you must assign an initial value to the variable const myVariable = 'initial'
. The variable is non exposed to the uninitialized state and accessing undefined
is impossible.
Let'due south check the function that verifies whether a word is a palindrome:
javascript
function isPalindrome ( word ) {
const length = word . length ;
const one-half = Math . floor ( length / 2 );
for ( permit index = 0 ; index < one-half ; alphabetize ++) {
if ( word [ alphabetize ] !== discussion [ length - index - 1 ]) {
render false ;
}
}
return truthful ;
}
isPalindrome ( 'madam' ); // => true
isPalindrome ( 'hello' ); // => false
length
and half
variables are assigned with a value once. It seems reasonable to declare them as const
since these variables aren't going to change.
Employ let
announcement for variables whose value can change. Whenever possible assign an initial value right away, due east.g. let alphabetize = 0
.
What about the sometime school var
? My suggestion is to stop using it.
var
declaration trouble is the variable hoisting within the office telescopic. You can declare a var
variable somewhere at the end of the function telescopic, but still, yous can access it before announcement: and y'all'll become an undefined
.
javascript
function bigFunction () {
// code...
myVariable ; // => undefined
// lawmaking...
var myVariable = 'Initial value' ;
// code...
myVariable ; // => 'Initial value'
}
bigFunction ();
myVariable
is attainable and contains undefined
fifty-fifty earlier the announcement line: var myVariable = 'Initial value'
.
Reverse, a const
or let
variable cannot be accessed before the declaration line — the variable is in a temporal dead zone before the announcement. And that's prissy because you have less take chances to access an undefined
.
The above example updated with let
(instead of var
) throws a ReferenceError
because the variable in the temporal expressionless zone is not attainable.
javascript
function bigFunction () {
// code...
myVariable ; // => Throws 'ReferenceError: myVariable is not divers'
// code...
let myVariable = 'Initial value' ;
// code...
myVariable ; // => 'Initial value'
}
bigFunction ();
Encouraging the usage of const
for immutable bindings or allow
otherwise ensures a practice that reduces the appearance of the uninitialized variable.
Tip 2: Increase cohesion
Cohesion characterizes the degree to which the elements of a module (namespace, class, method, cake of code) belong together. The cohesion tin exist high or low.
A high cohesion module is preferable considering the elements of such a module focus solely on a single task. Information technology makes the module:
- Focused and understandable: easier to sympathize what the module does
- Maintainable and easier to refactor: the change in the module affects fewer modules
- Reusable: beingness focused on a single task, information technology makes the module easier to reuse
- Testable: you would easier examination a module that's focused on a unmarried task
High cohesion accompanied by loose coupling is the characteristic of a well-designed system.
A code block can be considered a small module. To turn a profit from the benefits of high cohesion, proceed the variables equally close as possible to the code cake that uses them.
For instance, if a variable solely exists to form the logic of block scope, then declare and make the variable live only within that block (using const
or let
declarations). Do not betrayal this variable to the outer cake scope, since the outer block shouldn't care about this variable.
1 classic case of the unnecessarily extended life of variables is the usage of for
bike within a office:
javascript
function someFunc ( assortment ) {
var index , particular , length = array . length ;
// some code...
// some lawmaking...
for ( index = 0 ; index < length ; index ++) {
item = assortment [ index ];
// some code...
}
return 'some upshot' ;
}
index
, detail
and length
variables are declared at the beginning of the office torso. Yet, they are used merely nearly the end. What's the trouble with this approach?
Between the annunciation at the pinnacle and the usage in for
statement the variables index
, item
are uninitialized and exposed to undefined
. They have an unreasonably long lifecycle in the unabridged function scope.
A better approach is to move these variables as close equally possible to their usage place:
javascript
function someFunc ( array ) {
// some lawmaking...
// some code...
const length = array . length ;
for ( let alphabetize = 0 ; index < length ; index ++) {
const item = array [ index ];
// some
}
render 'some result' ;
}
alphabetize
and item
variables exist only in the block scope of for
statement. They don't have whatever meaning outside of for
.
length
variable is alleged close to the source of its usage too.
Why is the modified version better than the initial one? Let'southward come across:
- The variables are non exposed to uninitialized state, thus you have no take chances of accessing
undefined
- Moving the variables equally close every bit possible to their usage place increases the code readability
- High cohesive chunks of code are easier to refactor and extract into separate functions, if necessary
2.2 Accessing a non-existing property
When accessing a non-existing object property, JavaScript returns
undefined
.
Let's demonstrate that in an example:
javascript
allow favoriteMovie = {
title: 'Blade Runner'
};
favoriteMovie . actors ; // => undefined
favoriteMovie
is an object with a single holding title
. Accessing a non-existing belongings actors
using a property accessor favoriteMovie.actors
evaluates to undefined
.
Accessing a non-existing property does not throw an error. The problem appears when trying to get information from the non-existing property, which is the almost common undefined
trap, reflected in the well-known mistake bulletin TypeError: Cannot read property <prop> of undefined
.
Let's slightly modify the previous code snippet to illustrate a TypeError
throw:
javascript
let favoriteMovie = {
title: 'Blade Runner'
};
favoriteMovie . actors [ 0 ];
// TypeError: Cannot read property '0' of undefined
favoriteMovie
does non take the property actors
, and then favoriteMovie.actors
evaluates to undefined
.
As a event, accessing the first item of an undefined
value using the expression favoriteMovie.actors[0]
throws a TypeError
.
The permissive nature of JavaScript that allows accessing not-existing properties is a source of nondeterminism: the holding may be set or not. The good mode to bypass this problem is to restrict the object to have e'er defined the properties that information technology holds.
Unfortunately, often you don't have control over the objects. Such objects may have a unlike set up of properties in diverse scenarios. So you have to handle all these scenarios manually.
Allow'south implement a role append(assortment, toAppend)
that adds at the starting time and/or at the end of an assortment of new elements. toAppend
parameter accepts an object with backdrop:
-
first
: chemical element inserted at the beginning ofarray
-
last
: element inserted at the end ofarray
.
The function returns a new array instance, without altering the original array.
The first version of suspend()
, a bit naive, may look like this:
javascript
part append ( array , toAppend ) {
const arrayCopy = [... array ];
if ( toAppend . offset ) {
arrayCopy . unshift ( toAppend . first );
}
if ( toAppend . last ) {
arrayCopy . push ( toAppend . final );
}
return arrayCopy ;
}
append ([ 2 , 3 , 4 ], { outset: 1 , terminal: 5 }); // => [1, 2, 3, 4, 5]
suspend ([ 'Hello' ], { concluding: 'World' }); // => ['Hello', 'World']
suspend ([ eight , 16 ], { first: 4 }); // => [4, 8, 16]
Because toAppend
object tin omit first
or last
properties, information technology is obligatory to verify whether these properties exist in toAppend
.
A property accessor evaluates to undefined
if the holding does not exist. The starting time temptation to check whether first
or concluding
properties are nowadays is to verify them against undefined
. This is performed in conditionals if(toAppend.first){}
and if(toAppend.concluding){}
...
Non so fast. This approach has a drawback. undefined
, equally well as false
, null
, 0
, NaN
and ''
are falsy values.
In the current implementation of suspend()
, the function doesn't let to insert falsy elements:
javascript
append ([ 10 ], { start: 0 , last: false }); // => [10]
0
and false
are falsy. Considering if(toAppend.first){}
and if(toAppend.last){}
actually compare confronting falsy, these elements are non inserted into the array. The function returns the initial array [10]
without modifications, instead of the expected [0, 10, faux]
.
The tips that follow explicate how to correctly check the property'south beingness.
Tip three: Check the property beingness
Fortunately, JavaScript offers a bunch of means to determine if the object has a specific property:
-
obj.prop !== undefined
: compare againstundefined
directly -
typeof obj.prop !== 'undefined'
: verify the belongings value type -
obj.hasOwnProperty('prop')
: verify whether the object has an ain property -
'prop' in obj
: verify whether the object has an own or inherited property
My recommendation is to use in
operator. It has a brusque and sweet syntax. in
operator presence suggests a clear intent of checking whether an object has a specific holding, without accessing the actual holding value.
obj.hasOwnProperty('prop')
is a overnice solution too. Information technology'due south slightly longer than in
operator and verifies simply in the object's ain backdrop.
Let'due south ameliorate append(assortment, toAppend)
office using in
operator:
javascript
function suspend ( array , toAppend ) {
const arrayCopy = array . slice ();
if ( 'first' in toAppend ) {
arrayCopy . unshift ( toAppend . showtime );
}
if ( 'concluding' in toAppend ) {
arrayCopy . push ( toAppend . concluding );
}
return arrayCopy ;
}
append ([ 2 , iii , 4 ], { first: ane , terminal: five }); // => [i, two, 3, 4, 5]
append ([ 10 ], { showtime: 0 , final: fake }); // => [0, 10, false]
'offset' in toAppend
(and 'concluding' in toAppend
) is true
whether the corresponding property exists, fake
otherwise.
in
operator fixes the trouble with inserting falsy elements 0
and false
. Now, adding these elements at the offset and the end of [10]
produces the expected result [0, x, false]
.
Tip 4: Destructuring to access object backdrop
When accessing an object property, sometimes information technology's necessary to set a default value if the property does not exist.
Yous might utilise in
accompanied with ternary operator to reach that:
javascript
const object = { };
const prop = 'prop' in object ? object . prop : 'default' ;
prop ; // => 'default'
Ternary operator syntax becomes daunting when the number of properties to check increases. For each property, you take to create a new line of code to handle the defaults, increasing an ugly wall of similar-looking ternary operators.
To use a more elegant approach, let'southward become familiar with a great ES2015 feature called object destructuring.
Object destructuring allows inline extraction of object property values directly into variables and setting a default value if the property does not exist. A user-friendly syntax to avoid dealing directly with undefined
.
Indeed, the property extraction is at present precise:
javascript
const object = { };
const { prop = 'default' } = object ;
prop ; // => 'default'
To see things in activeness, allow's define a useful part that wraps a string in quotes.
quote(subject, config)
accepts the first argument equally the string to be wrapped. The second argument config
is an object with the properties:
-
char
: the quote char, e.yard.'
(single quote) or"
(double quote). Defaults to"
. -
skipIfQuoted
: the boolean value to skip quoting if the string is already quoted. Defaults totrue
.
Applying the benefits of the object destructuring, allow's implement quote()
:
javascript
office quote ( str , config ) {
const { char = '"' , skipIfQuoted = truthful } = config ;
const length = str . length ;
if ( skipIfQuoted
&& str [ 0 ] === char
&& str [ length - 1 ] === char ) {
return str ;
}
return char + str + char ;
}
quote ( 'Hello World' , { char: '*' }); // => '*Hello World*'
quote ( '"Welcome"' , { skipIfQuoted: truthful }); // => '"Welcome"'
const { char = '"', skipIfQuoted = true } = config
destructuring assignment in i line extracts the backdrop char
and skipIfQuoted
from config
object.
If some properties are missing in the config
object, the destructuring assignment sets the default values: '"'
for char
and imitation
for skipIfQuoted
.
Fortunately, the part still has room for improvement.
Let'due south motility the destructuring consignment into the parameters section. And set a default value (an empty object { }
) for the config
parameter, to skip the 2d argument when default settings are enough.
javascript
function quote ( str , { char = '"' , skipIfQuoted = true } = {}) {
const length = str . length ;
if ( skipIfQuoted
&& str [ 0 ] === char
&& str [ length - 1 ] === char ) {
return str ;
}
render char + str + char ;
}
quote ( 'Hello Earth' , { char: '*' }); // => '*How-do-you-do World*'
quote ( 'Sunny day' ); // => '"Sunny day"'
The destructuring consignment replaces the config
parameter in the function's signature. I like that: quote()
becomes one line shorter.
= {}
on the right side of the destructuring assignment ensures that an empty object is used if the second argument is non specified at all quote('Sunny solar day')
.
Object destructuring is a powerful feature that handles efficiently the extraction of backdrop from objects. I like the possibility to specify a default value to be returned when the accessed belongings doesn't be. As a result, you lot avoid undefined
and the hassle around it.
Tip five: Make full the object with default properties
If there is no need to create variables for every property, equally the destructuring assignment does, the object that misses some properties tin be filled with default values.
The ES2015 Object.assign(target, source1, source2, ...)
copies the values of all enumerable own properties from one or more than source objects into the target object. The function returns the target object.
For example, you need to access the properties of unsafeOptions
object that doesn't always incorporate its full set of properties.
To avoid undefined
when accessing a not-existing property from unsafeOptions
, let's make some adjustments:
- Define an object
defaults
that holds the default property values - Call
Object.assign({ }, defaults, unsafeOptions)
to build a new objectoptions
. The new object receives all properties fromunsafeOptions
, merely the missing ones are taken fromdefaults
.
javascript
const unsafeOptions = {
fontSize: 18
};
const defaults = {
fontSize: 16 ,
colour: 'black'
};
const options = Object . assign ({}, defaults , unsafeOptions );
options . fontSize ; // => xviii
options . colour ; // => 'black'
unsafeOptions
contains only fontSize
property. defaults
object defines the default values for properties fontSize
and colour
.
Object.assign()
takes the first argument as a target object {}
. The target object receives the value of fontSize
property from unsafeOptions
source object. And the value of color
property from defaults
source object, because unsafeOptions
doesn't contain color
.
The order in which the source objects are enumerated does thing: afterwards source object properties overwrite before ones.
You are now safety to access any property of options
object, including options.color
that wasn't available in unsafeOptions
initially.
Fortunately, an easier alternative to fill the object with default properties exists. I recommend to utilize the spread properties in object initializers.
Instead of Object.assign()
invocation, use the object spread syntax to copy into target object all own and enumerable backdrop from source objects:
javascript
const unsafeOptions = {
fontSize: 18
};
const defaults = {
fontSize: 16 ,
color: 'black'
};
const options = {
... defaults ,
... unsafeOptions
};
options . fontSize ; // => 18
options . colour ; // => 'black'
The object initializer spreads properties from defaults
and unsafeOptions
source objects. The guild in which the source objects are specified is important: later source object backdrop overwrite earlier ones.
Filling an incomplete object with default holding values is an efficient strategy to make your lawmaking condom and durable. No matter the situation, the object e'er contains the full set of properties: and undefined
cannot be generated.
Bonus tip: nullish coalescing
The operator nullish coalescing evaluates to a default value when its operand is undefined
or null
:
javascript
const value = nullOrUndefinedValue ?? defaultValue ;
Nullish coalescing operator is convenient to access an object belongings while having a default value when this property is undefined
or null
:
javascript
const styles = {
fontSize: 18
};
styles . color ?? 'black' ; // => 'blackness'
styles . fontSize ?? xvi ; // => 18
styles
object doesn't take the holding color
, thus styles.color
property accessor is undefined
. styles.color ?? 'blackness'
evaluates to the default value 'black'
.
styles.fontSize
is xviii
, so the nullish coalescing operator evaluates to the holding value 18
.
2.iii Function parameters
The function parameters implicitly default to
undefined
.
Commonly a office defined with a specific number of parameters should be invoked with the same number of arguments. That'due south when the parameters get the values you expect:
javascript
role multiply ( a , b ) {
a ; // => v
b ; // => 3
render a * b ;
}
multiply ( v , iii ); // => 15
When multiply(5, three)
, the parameters a
and b
receive five
and respectively three
values. The multiplication is calculated as expected: 5 * three = 15
.
What does happen when you omit an argument on invocation? The corresponding parameter inside the function becomes undefined
.
Permit's slightly modify the previous instance by calling the function with but i statement:
javascript
function multiply ( a , b ) {
a ; // => 5
b ; // => undefined
render a * b ;
}
multiply ( five ); // => NaN
The invocation multiply(5)
is performed with a single argument: as result a
parameter is 5
, merely the b
parameter is undefined
.
Tip 6: Employ default parameter value
Sometimes a role does non require the full set of arguments on invocation. You lot tin can set defaults for parameters that don't have a value.
Recalling the previous instance, permit'southward make an improvement. If b
parameter is undefined
, let default information technology to 2
:
javascript
function multiply ( a , b ) {
if ( b === undefined ) {
b = 2 ;
}
a ; // => 5
b ; // => 2
return a * b ;
}
multiply ( 5 ); // => x
The function is invoked with a single argument multiply(5)
. Initially, a
parameter is 2
and b
is undefined
.
The conditional statement verifies whether b
is undefined
. If it happens, b = 2
assignment sets a default value.
While the provided way to assign default values works, I don't recommend comparing directly against undefined
. It's verbose and looks similar a hack.
A better approach is to employ the ES2015 default parameters characteristic. It's short, expressive and no directly comparisons with undefined
.
Calculation a default value to parameter b = 2
looks better:
javascript
role multiply ( a , b = 2 ) {
a ; // => 5
b ; // => 2
return a * b ;
}
multiply ( five ); // => 10
multiply ( five , undefined ); // => ten
b = 2
in the office signature makes sure that if b
is undefined
, the parameter defaults to 2
.
ES2015 default parameters feature is intuitive and expressive. Always use it to set default values for optional parameters.
two.four Function return value
Implicitly, without
return
statement, a JavaScript function returnsundefined
.
A function that doesn't have return
statement implicitly returns undefined
:
javascript
function square ( x ) {
const res = 10 * x ;
}
foursquare ( 2 ); // => undefined
foursquare()
function does non return any ciphering results. The function invocation consequence is undefined
.
The same situation happens when return
statement is nowadays, but without an expression nearby:
javascript
function square ( x ) {
const res = x * ten ;
return ;
}
foursquare ( 2 ); // => undefined
return;
statement is executed, but information technology doesn't return any expression. The invocation outcome is as well undefined
.
Of course, indicating nigh return
the expression to be returned works as expected:
javascript
function square ( x ) {
const res = x * x ;
return res ;
}
square ( 2 ); // => iv
Now the office invocation is evaluated to four
, which is 2
squared.
Tip 7: Don't trust the automated semicolon insertion
The post-obit listing of statements in JavaScript must end with semicolons (;
):
- empty argument
-
let
,const
,var
,import
,export
declarations - expression statement
-
debugger
statement -
continue
argument,break
statement -
throw
statement -
return
argument
If you utilise ane of the above statements, exist sure to indicate a semicolon at the end:
javascript
role getNum () {
// Notice the semicolons at the cease
let num = i ;
render num ;
}
getNum (); // => one
At the end of both let
declaration and return
argument an obligatory semicolon is written.
What happens when you don't want to indicate these semicolons? In such a situation ECMAScript provides an Automatic Semicolon Insertion (ASI) mechanism, which inserts for you the missing semicolons.
Helped past ASI, you can remove the semicolons from the previous example:
javascript
function getNum () {
// Observe that semicolons are missing
permit num = 1
render num
}
getNum () // => 1
The above text is a valid JavaScript lawmaking. The missing semicolons are automatically inserted for you.
At first sight, it looks pretty promising. ASI machinery lets you skip the unnecessary semicolons. Y'all tin can make the JavaScript code smaller and easier to read.
There is one small, but annoying trap created by ASI. When a newline stands betwixt return
and the returned expression return \n expression
, ASI automatically inserts a semicolon before the newline return; \n expression
.
What it does mean inside a role to have render;
statement? The function returns undefined
. If you don't know in item the machinery of ASI, the unexpectedly returned undefined
is misleading.
For instance, let's study the returned value of getPrimeNumbers()
invocation:
javascript
part getPrimeNumbers () {
return
[ 2 , 3 , v , 7 , 11 , 13 , 17 ]
}
getPrimeNumbers () // => undefined
Betwixt render
statement and the array literal expression exists a new line. JavaScript automatically inserts a semicolon after return
, interpreting the code as follows:
javascript
function getPrimeNumbers () {
return ;
[ two , 3 , v , 7 , eleven , 13 , 17 ];
}
getPrimeNumbers (); // => undefined
The statement return;
makes the role getPrimeNumbers()
to return undefined
instead of the expected array.
The problem is solved by removing the newline between return
and array literal:
javascript
function getPrimeNumbers () {
return [
2 , 3 , five , seven , 11 , 13 , 17
];
}
getPrimeNumbers (); // => [2, 3, five, 7, 11, 13, 17]
My recommendation is to study how exactly Automated Semicolon Insertion works to avoid such situations.
Of form, never put a newline between return
and the returned expression.
2.v void operator
void <expression>
evaluates the expression and returns undefined
no matter the result of the evaluation.
javascript
void one ; // => undefined
void ( faux ); // => undefined
void {name: 'John Smith' }; // => undefined
void Math . min ( 1 , iii ); // => undefined
One utilize example of void
operator is to suppress expression evaluation to undefined
, relying on some side-result of the evaluation.
3. undefined in arrays
You get undefined
when accessing an array element with an out of premises index.
javascript
const colors = [ 'blue' , 'white' , 'red' ];
colors [ 5 ]; // => undefined
colors [- one ]; // => undefined
colors
array has 3 elements, thus valid indexes are 0
, 1
, and 2
.
Because there are no array elements at indexes 5
and -1
, the accessors colors[5]
and colors[-i]
are undefined
.
In JavaScript, you might run across and so-called sparse arrays. Theses are arrays that accept gaps, i.eastward. at some indexes, no elements are defined.
When a gap (aka empty slot) is accessed inside a thin array, you as well go an undefined
.
The following instance generates sparse arrays and tries to access their empty slots:
javascript
const sparse1 = new Array ( iii );
sparse1 ; // => [<empty slot>, <empty slot>, <empty slot>]
sparse1 [ 0 ]; // => undefined
sparse1 [ i ]; // => undefined
const sparse2 = [ 'white' , , 'bluish' ]
sparse2 ; // => ['white', <empty slot>, 'blueish']
sparse2 [ 1 ]; // => undefined
sparse1
is created by invoking an Assortment
constructor with a numeric get-go statement. It has iii empty slots.
sparse2
is created with an array literal with the missing 2d element.
In any of these sparse arrays accessing an empty slot evaluates to undefined
.
When working with arrays, to avoid undefined
, be certain to employ valid array indexes and forbid the creation of sparse arrays.
4. Divergence betwixt undefined and null
What is the main departure betwixt undefined
and null
? Both special values imply an empty country.
undefined
represents the value of a variable that hasn't been yet initialized, whilenull
represents an intentional absence of an object.
Let's explore the difference in some examples.
The variable number
is defined, however, is not assigned with an initial value:
javascript
let number ;
number ; // => undefined
number
variable is undefined
, which indicates an uninitialized variable.
The same uninitialized concept happens when a not-existing object property is accessed:
javascript
const obj = { firstName: 'Dmitri' };
obj . lastName ; // => undefined
Because lastName
property does not be in obj
, JavaScript evaluates obj.lastName
to undefined
.
On the other side, yous know that a variable expects an object. Merely for some reason, you tin't instantiate the object. In such case zilch
is a meaningful indicator of a missing object.
For example, clone()
is a role that clones a plain JavaScript object. The function is expected to return an object:
javascript
function clone ( obj ) {
if ( typeof obj === 'object' && obj !== aught ) {
return Object . assign ({}, obj );
}
return null ;
}
clone ({ name: 'John' }); // => {name: 'John'}
clone ( 15 ); // => zippo
clone ( null ); // => nil
However clone()
might be invoked with a not-object argument: 15
or null
. In such a case, the role cannot create a clone, so it returns nada
— the indicator of a missing object.
typeof
operator makes the distinction between undefined
and null
:
javascript
typeof undefined ; // => 'undefined'
typeof null ; // => 'object'
Also the strict quality operator ===
correctly differentiates undefined
from null
:
javascript
permit nothing = undefined ;
allow missingObject = goose egg ;
zippo === missingObject ; // => false
v. Conclusion
undefined
beingness is a result of JavaScript's permissive nature that allows the usage of:
- uninitialized variables
- non-existing object properties or methods
- out of bounds indexes to access array elements
- the invocation result of a function that returns zip
Comparison directly against undefined
is dangerous because you rely on a permitted but discouraged practise mentioned above.
An efficient strategy is to reduce at minimum the appearance of undefined
keyword in your code past applying practiced habits such as:
- reduce the usage of uninitialized variables
- make the variables lifecycle short and close to the source of their usage
- whenever possible assign initial values to variables
- favor
const
, otherwise uselet
- use default values for insignificant function parameters
- verify the properties existence or fill the unsafe objects with default properties
- avert the usage of sparse arrays
Is it good that JavaScript has both undefined
and zilch
to stand for empty values?
Source: https://dmitripavlutin.com/7-tips-to-handle-undefined-in-javascript/
0 Response to "Typeerror Cannot Read Property 'length' of Undefined Javascript"
Post a Comment