Cannot Read Property 'call' of Undefined Javascript Stackoverflow
Most of the mod languages like Ruby, Python, or Java take a single zero value (nil
or null
), which seems a reasonable approach.
But JavaScript is dissimilar.
null
, but also undefined
, represent in JavaScript empty values. So what'south the exact deviation between them?
The brusque reply is that JavaScript interpreter returns undefined
when accessing a variable or object belongings that is not yet initialized. For instance:
javascript
permit visitor ;
company ; // => undefined
let person = { proper noun: 'John Smith' };
person . age ; // => undefined
On the other side, null
represents a missing object reference. JavaScript doesn't initialize variables or object backdrop with cipher
.
Some native methods like String.prototype.match()
can return null
to denote a missing object. Take a look at the sample:
javascript
let assortment = aught ;
array ; // => null
let film = { name: 'Starship Troopers' , musicBy: null };
moving picture . musicBy ; // => null
'abc' . match ( / [ 0-nine ] / ); // => null
Because JavaScript is permissive, developers have the temptation to admission uninitialized values. I'm guilty of such bad practice as well.
Often such risky actions generate undefined
related errors:
-
TypeError: 'undefined' is non a part
-
TypeError: Cannot read holding '<prop-proper name>' of undefined
- and akin type errors.
JavaScript developer can understand the irony of this joke:
javascript
function undefined () {
// problem solved
}
To reduce such errors, y'all have to understand the cases when undefined
is generated. Permit'due south explore undefined
and its effect on code safety.
Table of Contents
- ane. What is undefined
- ii. Scenarios that create undefined
- 2.1 Uninitialized variable
- 2.ii Accessing a non-existing property
- two.3 Function parameters
- 2.4 Function return value
- 2.5 void operator
- 3. undefined in arrays
- iv. Deviation betwixt undefined and zippo
- five. Conclusion
1. What is undefined
JavaScript has vi primitive types:
- Boolean:
true
orfake
- Number:
1
,6.vii
,0xFF
- String:
"Gorilla and banana"
- Symbol:
Symbol("name")
(starting ES2015) - Nil:
cypher
- Undefined:
undefined
.
And a separated object type: {name: "Dmitri"}
, ["apple", "orange"]
.
From vi primitive types undefined
is a special value with its own blazon Undefined. According to ECMAScript specification:
Undefined value archaic value is used when a variable has non been assigned a value.
The standard clearly defines that you volition receive undefined
when accessing uninitialized variables, non-existing object properties, non-existing array elements, and alike.
A few examples:
javascript
permit number ;
number ; // => undefined
let film = { name: 'Interstellar' };
picture . year ; // => undefined
let movies = [ 'Interstellar' , 'Alexander' ];
movies [ 3 ]; // => undefined
The above example demonstrates that accessing:
- an uninitialized variable
number
- a not-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' ; // => true
Of course typeof
works nicely to verify whether a variable contains an undefined
value:
javascript
let nothing ;
typeof nothing === 'undefined' ; // => truthful
two. Scenarios that create undefined
2.1 Uninitialized variable
A declared variable merely not yet assigned with a value (uninitialized) is by default
undefined
.
Manifestly and simple:
javascript
permit myVariable ;
myVariable ; // => undefined
myVariable
is alleged and non nevertheless 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 state, the ameliorate.
Ideally, you would assign a value right abroad after annunciation const myVariable = 'Initial value'
. But that's non always possible.
Tip 1: Favor const
, otherwise use permit
, just say farewell to var
In my stance, one of the all-time features of ECMAScript 2015 is the new manner to declare variables using const
and let
. Information technology is a big footstep frontward.
const
and let
are block scoped (opposite to older function scoped var
) and exist in a temporal dead zone until the declaration line.
I recommend const
variable when its value is not going to modify. It creates an immutable bounden.
I of the dainty features of const
is that you must assign an initial value to the variable const myVariable = 'initial'
. The variable is not exposed to the uninitialized land and accessing undefined
is incommunicable.
Let'southward check the function that verifies whether a discussion is a palindrome:
javascript
function isPalindrome ( word ) {
const length = word . length ;
const half = Math . flooring ( length / 2 );
for ( let index = 0 ; index < half ; index ++) {
if ( discussion [ index ] !== give-and-take [ length - index - one ]) {
return false ;
}
}
return true ;
}
isPalindrome ( 'madam' ); // => true
isPalindrome ( 'howdy' ); // => false
length
and half
variables are assigned with a value one time. 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, e.grand. let alphabetize = 0
.
What about the old schoolhouse var
? My proffer is to terminate using it.
var
declaration problem is the variable hoisting within the function telescopic. You can declare a var
variable somewhere at the end of the part scope, but notwithstanding, you can access information technology before announcement: and y'all'll get an undefined
.
javascript
office bigFunction () {
// code...
myVariable ; // => undefined
// code...
var myVariable = 'Initial value' ;
// code...
myVariable ; // => 'Initial value'
}
bigFunction ();
myVariable
is accessible and contains undefined
fifty-fifty before the annunciation line: var myVariable = 'Initial value'
.
Contrary, a const
or let
variable cannot be accessed earlier the proclamation line — the variable is in a temporal dead zone before the announcement. And that's dainty considering you have less chance to access an undefined
.
The above example updated with let
(instead of var
) throws a ReferenceError
because the variable in the temporal dead zone is not accessible.
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 permit
otherwise ensures a do that reduces the appearance of the uninitialized variable.
Tip 2: Increase cohesion
Cohesion characterizes the caste to which the elements of a module (namespace, form, method, block of code) belong together. The cohesion can be high or depression.
A high cohesion module is preferable considering the elements of such a module focus solely on a single job. It makes the module:
- Focused and understandable: easier to sympathise what the module does
- Maintainable and easier to refactor: the change in the module affects fewer modules
- Reusable: beingness focused on a single job, information technology makes the module easier to reuse
- Testable: you would easier examination a module that'southward focused on a unmarried task
Loftier cohesion accompanied past loose coupling is the characteristic of a well-designed system.
A lawmaking block can be considered a small module. To profit from the benefits of high cohesion, continue the variables every bit close equally possible to the lawmaking block that uses them.
For instance, if a variable solely exists to class the logic of block scope, then declare and make the variable alive only within that block (using const
or permit
declarations). Do not expose this variable to the outer cake scope, since the outer block shouldn't care almost this variable.
One classic example of the unnecessarily extended life of variables is the usage of for
wheel inside a function:
javascript
function someFunc ( array ) {
var index , particular , length = array . length ;
// some code...
// some code...
for ( index = 0 ; index < length ; index ++) {
particular = array [ index ];
// some code...
}
render 'some result' ;
}
alphabetize
, item
and length
variables are alleged at the beginning of the role body. However, they are used simply near the end. What's the trouble with this approach?
Between the announcement at the top and the usage in for
statement the variables index
, item
are uninitialized and exposed to undefined
. They take an unreasonably long lifecycle in the entire role scope.
A better approach is to move these variables as close as possible to their usage place:
javascript
function someFunc ( array ) {
// some code...
// some code...
const length = array . length ;
for ( let alphabetize = 0 ; index < length ; index ++) {
const item = array [ index ];
// some
}
return 'some issue' ;
}
index
and detail
variables exist only in the block scope of for
statement. They don't have any significant outside of for
.
length
variable is declared close to the source of its usage too.
Why is the modified version better than the initial i? Let'southward see:
- The variables are not exposed to uninitialized state, thus you take no risk of accessing
undefined
- Moving the variables every bit shut as possible to their usage place increases the code readability
- High cohesive chunks of lawmaking are easier to refactor and extract into dissever functions, if necessary
two.two Accessing a not-existing property
When accessing a non-existing object property, JavaScript returns
undefined
.
Permit's demonstrate that in an instance:
javascript
let favoriteMovie = {
title: 'Blade Runner'
};
favoriteMovie . actors ; // => undefined
favoriteMovie
is an object with a single property title
. Accessing a non-existing holding actors
using a holding accessor favoriteMovie.actors
evaluates to undefined
.
Accessing a non-existing property does not throw an mistake. The trouble appears when trying to become data from the not-existing property, which is the nearly common undefined
trap, reflected in the well-known fault message TypeError: Cannot read belongings <prop> of undefined
.
Permit'due south slightly modify the previous code snippet to illustrate a TypeError
throw:
javascript
let favoriteMovie = {
title: 'Blade Runner'
};
favoriteMovie . actors [ 0 ];
// TypeError: Cannot read belongings '0' of undefined
favoriteMovie
does not have the property actors
, so favoriteMovie.actors
evaluates to undefined
.
Every bit a result, accessing the starting time particular of an undefined
value using the expression favoriteMovie.actors[0]
throws a TypeError
.
The permissive nature of JavaScript that allows accessing non-existing properties is a source of nondeterminism: the property may be set or not. The good way to bypass this trouble is to restrict the object to have e'er defined the properties that it holds.
Unfortunately, oft you lot don't have command over the objects. Such objects may have a different ready of properties in diverse scenarios. So y'all accept to handle all these scenarios manually.
Let's implement a role append(array, toAppend)
that adds at the first and/or at the terminate of an array of new elements. toAppend
parameter accepts an object with properties:
-
first
: element inserted at the kickoff ofassortment
-
last
: element inserted at the finish ofassortment
.
The office returns a new array instance, without altering the original assortment.
The first version of append()
, a chip naive, may look similar this:
javascript
function append ( array , toAppend ) {
const arrayCopy = [... array ];
if ( toAppend . first ) {
arrayCopy . unshift ( toAppend . first );
}
if ( toAppend . final ) {
arrayCopy . push ( toAppend . last );
}
return arrayCopy ;
}
append ([ 2 , iii , 4 ], { first: 1 , final: 5 }); // => [1, 2, 3, 4, v]
append ([ 'Hello' ], { final: 'Earth' }); // => ['Hi', 'Earth']
append ([ 8 , sixteen ], { first: 4 }); // => [iv, viii, sixteen]
Because toAppend
object can omit start
or last
backdrop, it is obligatory to verify whether these properties be in toAppend
.
A property accessor evaluates to undefined
if the property does not exist. The first temptation to check whether commencement
or last
properties are present is to verify them confronting undefined
. This is performed in conditionals if(toAppend.first){}
and if(toAppend.last){}
...
Non and then fast. This approach has a drawback. undefined
, likewise as false
, aught
, 0
, NaN
and ''
are falsy values.
In the current implementation of suspend()
, the office doesn't allow to insert falsy elements:
javascript
append ([ 10 ], { commencement: 0 , last: false }); // => [ten]
0
and faux
are falsy. Considering if(toAppend.offset){}
and if(toAppend.last){}
really compare against falsy, these elements are not inserted into the assortment. The function returns the initial array [10]
without modifications, instead of the expected [0, x, false]
.
The tips that follow explicate how to correctly cheque the property'due south existence.
Tip iii: Check the property existence
Fortunately, JavaScript offers a bunch of means to determine if the object has a specific property:
-
obj.prop !== undefined
: compare confrontingundefined
directly -
typeof obj.prop !== 'undefined'
: verify the holding value type -
obj.hasOwnProperty('prop')
: verify whether the object has an own property -
'prop' in obj
: verify whether the object has an own or inherited property
My recommendation is to use in
operator. It has a short and sweet syntax. in
operator presence suggests a articulate intent of checking whether an object has a specific property, without accessing the bodily property value.
obj.hasOwnProperty('prop')
is a dainty solution besides. It'due south slightly longer than in
operator and verifies only in the object'due south own properties.
Permit'southward improve append(array, toAppend)
function using in
operator:
javascript
function append ( array , toAppend ) {
const arrayCopy = array . slice ();
if ( 'offset' in toAppend ) {
arrayCopy . unshift ( toAppend . first );
}
if ( 'concluding' in toAppend ) {
arrayCopy . push button ( toAppend . concluding );
}
render arrayCopy ;
}
append ([ 2 , 3 , four ], { first: i , last: five }); // => [1, 2, 3, four, 5]
suspend ([ 10 ], { first: 0 , last: false }); // => [0, 10, imitation]
'first' in toAppend
(and 'terminal' in toAppend
) is true
whether the corresponding property exists, false
otherwise.
in
operator fixes the problem with inserting falsy elements 0
and false
. Now, calculation these elements at the beginning and the cease of [10]
produces the expected result [0, 10, false]
.
Tip 4: Destructuring to access object properties
When accessing an object property, sometimes it's necessary to set a default value if the property does not exist.
You might use in
accompanied with ternary operator to accomplish 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 have to create a new line of code to handle the defaults, increasing an ugly wall of similar-looking ternary operators.
To utilise a more than elegant approach, let's become familiar with a bully 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 non exist. A convenient syntax to avoid dealing straight with undefined
.
Indeed, the property extraction is at present precise:
javascript
const object = { };
const { prop = 'default' } = object ;
prop ; // => 'default'
To see things in activeness, let's define a useful function that wraps a string in quotes.
quote(subject, config)
accepts the first argument as the string to be wrapped. The second statement config
is an object with the properties:
-
char
: the quote char, east.g.'
(single quote) or"
(double quote). Defaults to"
. -
skipIfQuoted
: the boolean value to skip quoting if the string is already quoted. Defaults totruthful
.
Applying the benefits of the object destructuring, let's implement quote()
:
javascript
function quote ( str , config ) {
const { char = '"' , skipIfQuoted = true } = config ;
const length = str . length ;
if ( skipIfQuoted
&& str [ 0 ] === char
&& str [ length - 1 ] === char ) {
return str ;
}
return char + str + char ;
}
quote ( 'Howdy World' , { char: '*' }); // => '*Hello Globe*'
quote ( '"Welcome"' , { skipIfQuoted: true }); // => '"Welcome"'
const { char = '"', skipIfQuoted = truthful } = config
destructuring assignment in one 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 false
for skipIfQuoted
.
Fortunately, the function still has room for improvement.
Permit'due south movement the destructuring assignment into the parameters section. And ready a default value (an empty object { }
) for the config
parameter, to skip the second argument when default settings are enough.
javascript
office quote ( str , { char = '"' , skipIfQuoted = truthful } = {}) {
const length = str . length ;
if ( skipIfQuoted
&& str [ 0 ] === char
&& str [ length - 1 ] === char ) {
return str ;
}
return char + str + char ;
}
quote ( 'Hello World' , { char: '*' }); // => '*Hi World*'
quote ( 'Sunny solar day' ); // => '"Sunny twenty-four hour period"'
The destructuring assignment replaces the config
parameter in the function'due south signature. I like that: quote()
becomes i line shorter.
= {}
on the right side of the destructuring assignment ensures that an empty object is used if the second statement is not specified at all quote('Sunny day')
.
Object destructuring is a powerful feature that handles efficiently the extraction of properties from objects. I like the possibility to specify a default value to exist returned when the accessed property doesn't exist. As a consequence, you avoid undefined
and the hassle around it.
Tip 5: Make full the object with default properties
If there is no need to create variables for every belongings, as the destructuring consignment does, the object that misses some backdrop tin can exist filled with default values.
The ES2015 Object.assign(target, source1, source2, ...)
copies the values of all enumerable ain properties from one or more source objects into the target object. The role returns the target object.
For instance, you demand to access the properties of unsafeOptions
object that doesn't always contain its full set of backdrop.
To avoid undefined
when accessing a non-existing holding from unsafeOptions
, permit's make some adjustments:
- Ascertain 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
, but the missing ones are taken fromdefaults
.
javascript
const unsafeOptions = {
fontSize: 18
};
const defaults = {
fontSize: sixteen ,
color: 'blackness'
};
const options = Object . assign ({}, defaults , unsafeOptions );
options . fontSize ; // => 18
options . color ; // => 'black'
unsafeOptions
contains only fontSize
belongings. defaults
object defines the default values for backdrop fontSize
and color
.
Object.assign()
takes the starting time argument as a target object {}
. The target object receives the value of fontSize
holding from unsafeOptions
source object. And the value of color
property from defaults
source object, because unsafeOptions
doesn't contain colour
.
The gild in which the source objects are enumerated does matter: later on source object backdrop overwrite earlier ones.
Yous are now safe to admission any holding of options
object, including options.colour
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 re-create into target object all own and enumerable properties from source objects:
javascript
const unsafeOptions = {
fontSize: xviii
};
const defaults = {
fontSize: 16 ,
color: 'black'
};
const options = {
... defaults ,
... unsafeOptions
};
options . fontSize ; // => 18
options . color ; // => 'black'
The object initializer spreads properties from defaults
and unsafeOptions
source objects. The guild in which the source objects are specified is of import: later on source object backdrop overwrite earlier ones.
Filling an incomplete object with default belongings values is an efficient strategy to make your code safe and durable. No affair the situation, the object e'er contains the total set of backdrop: 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 user-friendly to access an object property while having a default value when this holding is undefined
or zilch
:
javascript
const styles = {
fontSize: 18
};
styles . colour ?? 'black' ; // => 'black'
styles . fontSize ?? sixteen ; // => 18
styles
object doesn't have the property color
, thus styles.colour
property accessor is undefined
. styles.color ?? 'blackness'
evaluates to the default value 'black'
.
styles.fontSize
is xviii
, then the nullish coalescing operator evaluates to the property value 18
.
2.3 Function parameters
The function parameters implicitly default to
undefined
.
Usually a part divers with a specific number of parameters should be invoked with the aforementioned number of arguments. That's when the parameters get the values y'all expect:
javascript
function multiply ( a , b ) {
a ; // => 5
b ; // => 3
return a * b ;
}
multiply ( v , 3 ); // => 15
When multiply(5, 3)
, the parameters a
and b
receive 5
and respectively iii
values. The multiplication is calculated equally expected: five * iii = xv
.
What does happen when y'all omit an statement on invocation? The corresponding parameter inside the role becomes undefined
.
Let's slightly modify the previous example by calling the function with just 1 argument:
javascript
office multiply ( a , b ) {
a ; // => 5
b ; // => undefined
return a * b ;
}
multiply ( 5 ); // => NaN
The invocation multiply(5)
is performed with a unmarried argument: as upshot a
parameter is 5
, but the b
parameter is undefined
.
Tip 6: Use default parameter value
Sometimes a function does not require the full set of arguments on invocation. Yous can fix defaults for parameters that don't have a value.
Recalling the previous case, let'due south make an improvement. If b
parameter is undefined
, let default it to 2
:
javascript
function multiply ( a , b ) {
if ( b === undefined ) {
b = ii ;
}
a ; // => 5
b ; // => 2
render a * b ;
}
multiply ( v ); // => 10
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 comparison directly against undefined
. Information technology's verbose and looks similar a hack.
A improve approach is to utilize the ES2015 default parameters feature. It'southward short, expressive and no direct comparisons with undefined
.
Adding a default value to parameter b = 2
looks ameliorate:
javascript
office multiply ( a , b = 2 ) {
a ; // => v
b ; // => two
render a * b ;
}
multiply ( 5 ); // => x
multiply ( 5 , undefined ); // => x
b = two
in the function signature makes sure that if b
is undefined
, the parameter defaults to ii
.
ES2015 default parameters feature is intuitive and expressive. Always use it to set default values for optional parameters.
2.4 Part return value
Implicitly, without
return
statement, a JavaScript function returnsundefined
.
A part that doesn't take render
statement implicitly returns undefined
:
javascript
part square ( 10 ) {
const res = x * x ;
}
foursquare ( 2 ); // => undefined
square()
function does not render any computation results. The function invocation upshot is undefined
.
The same situation happens when return
statement is present, but without an expression nearby:
javascript
role square ( 10 ) {
const res = ten * x ;
return ;
}
square ( two ); // => undefined
return;
statement is executed, but information technology doesn't render any expression. The invocation outcome is too undefined
.
Of form, indicating near render
the expression to exist returned works as expected:
javascript
office square ( x ) {
const res = x * x ;
return res ;
}
square ( 2 ); // => four
Now the function invocation is evaluated to 4
, which is 2
squared.
Tip vii: Don't trust the automated semicolon insertion
The following list of statements in JavaScript must end with semicolons (;
):
- empty statement
-
let
,const
,var
,import
,export
declarations - expression statement
-
debugger
statement -
proceed
statement,break
statement -
throw
statement -
return
statement
If you utilize one of the in a higher place statements, exist sure to indicate a semicolon at the finish:
javascript
function getNum () {
// Notice the semicolons at the finish
permit num = i ;
return num ;
}
getNum (); // => one
At the end of both let
declaration and return
statement an obligatory semicolon is written.
What happens when you don't want to signal these semicolons? In such a state of affairs ECMAScript provides an Automatic Semicolon Insertion (ASI) machinery, which inserts for you the missing semicolons.
Helped by ASI, you lot can remove the semicolons from the previous instance:
javascript
function getNum () {
// Notice that semicolons are missing
let num = i
return num
}
getNum () // => 1
The above text is a valid JavaScript code. The missing semicolons are automatically inserted for you.
At first sight, information technology looks pretty promising. ASI machinery lets y'all skip the unnecessary semicolons. You can make the JavaScript code smaller and easier to read.
At that place is i minor, but annoying trap created by ASI. When a newline stands betwixt render
and the returned expression return \north expression
, ASI automatically inserts a semicolon earlier the newline return; \n expression
.
What it does hateful inside a function to take return;
argument? The function returns undefined
. If you don't know in particular the mechanism of ASI, the unexpectedly returned undefined
is misleading.
For instance, permit'due south written report the returned value of getPrimeNumbers()
invocation:
javascript
function getPrimeNumbers () {
return
[ two , 3 , v , seven , 11 , 13 , 17 ]
}
getPrimeNumbers () // => undefined
Between return
statement and the array literal expression exists a new line. JavaScript automatically inserts a semicolon afterwards return
, interpreting the code every bit follows:
javascript
function getPrimeNumbers () {
render ;
[ 2 , 3 , 5 , seven , xi , 13 , 17 ];
}
getPrimeNumbers (); // => undefined
The statement return;
makes the office getPrimeNumbers()
to return undefined
instead of the expected array.
The problem is solved past removing the newline between return
and array literal:
javascript
function getPrimeNumbers () {
return [
2 , iii , 5 , 7 , xi , 13 , 17
];
}
getPrimeNumbers (); // => [ii, 3, five, vii, 11, 13, 17]
My recommendation is to written report how exactly Automatic Semicolon Insertion works to avoid such situations.
Of course, never put a newline betwixt return
and the returned expression.
two.5 void operator
void <expression>
evaluates the expression and returns undefined
no matter the consequence of the evaluation.
javascript
void 1 ; // => undefined
void ( false ); // => undefined
void {proper noun: 'John Smith' }; // => undefined
void Math . min ( 1 , 3 ); // => undefined
I use instance of void
operator is to suppress expression evaluation to undefined
, relying on some side-upshot of the evaluation.
3. undefined in arrays
You get undefined
when accessing an assortment element with an out of bounds index.
javascript
const colors = [ 'blue' , 'white' , 'red' ];
colors [ 5 ]; // => undefined
colors [- 1 ]; // => undefined
colors
assortment has 3 elements, thus valid indexes are 0
, 1
, and two
.
Considering there are no assortment elements at indexes 5
and -1
, the accessors colors[v]
and colors[-one]
are undefined
.
In JavaScript, y'all might encounter so-called sparse arrays. Theses are arrays that have gaps, i.east. at some indexes, no elements are defined.
When a gap (aka empty slot) is accessed inside a sparse array, you lot likewise get an undefined
.
The post-obit example generates sparse arrays and tries to access their empty slots:
javascript
const sparse1 = new Array ( 3 );
sparse1 ; // => [<empty slot>, <empty slot>, <empty slot>]
sparse1 [ 0 ]; // => undefined
sparse1 [ one ]; // => undefined
const sparse2 = [ 'white' , , 'blue' ]
sparse2 ; // => ['white', <empty slot>, 'blue']
sparse2 [ 1 ]; // => undefined
sparse1
is created by invoking an Assortment
constructor with a numeric first argument. It has 3 empty slots.
sparse2
is created with an array literal with the missing 2d chemical element.
In any of these sparse arrays accessing an empty slot evaluates to undefined
.
When working with arrays, to avoid undefined
, be sure to apply valid array indexes and forbid the creation of thin arrays.
4. Divergence betwixt undefined and null
What is the chief difference between undefined
and nada
? Both special values imply an empty state.
undefined
represents the value of a variable that hasn't been yet initialized, whilenada
represents an intentional absence of an object.
Permit'southward explore the divergence in some examples.
The variable number
is defined, however, is non assigned with an initial value:
javascript
permit number ;
number ; // => undefined
number
variable is undefined
, which indicates an uninitialized variable.
The same uninitialized concept happens when a non-existing object holding is accessed:
javascript
const obj = { firstName: 'Dmitri' };
obj . lastName ; // => undefined
Because lastName
property does not exist in obj
, JavaScript evaluates obj.lastName
to undefined
.
On the other side, you know that a variable expects an object. Simply for some reason, you tin can't instantiate the object. In such case null
is a meaningful indicator of a missing object.
For example, clone()
is a function that clones a plain JavaScript object. The function is expected to return an object:
javascript
function clone ( obj ) {
if ( typeof obj === 'object' && obj !== null ) {
return Object . assign ({}, obj );
}
render zero ;
}
clone ({ name: 'John' }); // => {proper name: 'John'}
clone ( 15 ); // => naught
clone ( nada ); // => null
However clone()
might be invoked with a non-object statement: fifteen
or zero
. In such a case, the function cannot create a clone, and so it returns aught
— the indicator of a missing object.
typeof
operator makes the distinction betwixt undefined
and nada
:
javascript
typeof undefined ; // => 'undefined'
typeof cypher ; // => 'object'
Also the strict quality operator ===
correctly differentiates undefined
from cypher
:
javascript
let cipher = undefined ;
let missingObject = zilch ;
nada === missingObject ; // => simulated
5. Conclusion
undefined
beingness is a consequence of JavaScript's permissive nature that allows the usage of:
- uninitialized variables
- non-existing object properties or methods
- out of bounds indexes to access assortment elements
- the invocation result of a function that returns nothing
Comparison directly against undefined
is dangerous because you rely on a permitted but discouraged practice mentioned to a higher place.
An efficient strategy is to reduce at minimum the appearance of undefined
keyword in your code past applying good habits such every bit:
- reduce the usage of uninitialized variables
- make the variables lifecycle curt 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 backdrop being or make full the unsafe objects with default properties
- avoid the usage of thin arrays
Is it expert that JavaScript has both undefined
and aught
to stand for empty values?
Source: https://dmitripavlutin.com/7-tips-to-handle-undefined-in-javascript/
0 Response to "Cannot Read Property 'call' of Undefined Javascript Stackoverflow"
Post a Comment