Jun 01, 2021 Article blog
1. 1. Uncaught TypeError: Cannot read property
2. 2. TypeError: ‘undefined’ is not an object (evaluating
3. 3. TypeError: null is not an object (evaluating
5. 5. TypeError: Object doesn’t support property
6. 6. TypeError: ‘undefined’ is not a function
7. 7. Uncaught RangeError: Maximum call stack
8. 8. TypeError: Cannot read property ‘length’
9. 9. Uncaught TypeError: Cannot set property
This article is reproduced in public number: Front-end craftsman (microsignal: frontJS)
This article brings you 10 classic JavaScript errors, each of which has been shortened for ease of reading, so let's take a closer look at each question to determine what caused it and how to avoid it.
If you were a JavaScript developer, you might have seen this error. T his happens in Chrome when you read a property or call a method on an undefined object. You can easily test it in the Chrome developer console.
There are many reasons for this, but the common reason is that the state is not initialized properly when rendering UI components. L
et's look at an example of how this happens in a real-world application.
We'll select
React
but the same principle of incorrect initialization applies to
Angular
Vue
or any other framework.
class Quiz extends Component {
componentWillMount() {
axios.get('/thedata').then(res => {
this.setState({items: res.data});
});
}
render() {
return (
<ul>
{this.state.items.map(item =>
<li key={item.id}>{item.name}</li>
)}
</ul>
);
}
}
Here are two important things to realize:
this.state
starts with the
undefined
state.
componentWillMount
or
componentDidMount
the component renders the data at least once before it loads. W
hen Quiz first rendered,
this.state.items
were
undefined
This, in turn, means that SiteList gets an undefined items, and you get an error in the console - "UncaughtTypeError: Cannot read property'map' of undefined".
This is easy to solve and the easiest way to do this is to initialize the state with a reasonable default value in the constructor.
class Quiz extends Component {
// 添加了这个:
constructor(props) {
super(props);
this.state = {
items: [] // 默认值
};
}
componentWillMount() {
axios.get('/thedata').then(res => {
this.setState({items: res.data});
});
}
render() {
return (
<ul>
{this.state.items.map(item =>
<li key={item.id}>{item.name}</li>
)}
</ul>
);
}
}
The actual code in your application may be different, but I hope I've given you enough clues to fix or avoid this problem in your application. If not, read on, as I'll cover more examples of related errors below.
This is an error that occurs when you read a property in
Safari
or call a method on a
undefined
object, which you can test very easily in the
Safari
developer console.
This is basically the same as the error for Chrome mentioned above, but Safari uses a different error message.
This is an error that occurs when reading properties in Safari or calling methods on
null
objects, which you can test very easily in the Safari developer console.
Interestingly, in
JavaScript
null
and
undefined
are not the same, which is why we see two different error messages.
nk.
To verify that they are equal, try the Strict Equal operator.
One way this error might occur in a real-world example is to try using
DOM
element in
JavaScript
before loading the element because the
DOM API
returns
null
for a blank object reference.
Any
JS
code that executes and processes
DOM
elements should be executed after the
DOM
element is created.
JS
code is interpreted from top to bottom in
HTML
format, so if there is a label in the
DOM
element before it, the
JS
code within the script label is executed when the browser parses the
HTML
page.
This error occurs if
DOM
element was not created before the script was loaded.
In this example, we can resolve the issue by adding an event listener that will notify us when the page is ready.
Once
addEventListener
is triggered,
init()
method can use
DOM
element.
<script>
function init() {
var myButton = document.getElementById("myButton");
var myTextfield = document.getElementById("myTextfield");
myButton.onclick = function() {
var userName = myTextfield.value;
}
}
document.addEventListener('readystatechange', function() {
if (document.readyState === "complete") {
init();
}
});
</script>
<form>
<input type="text" id="myTextfield" placeholder="Type your name" />
<input type="button" id="myButton" value="Go" />
</form>
A script error occurs when an uncaptured
JavaScript
error violates a cross-source policy across domain boundaries. F
or example, if you host your
JavaScript
code on a
CDN
any uncaught errors (errors that bubble into the windows.onerror handler, rather than those caught in the terry-catch) are reported as "Script errors" instead of containing useful information.
This is a browser security measure designed to prevent data from being passed across domains that would otherwise be unable to communicate.
To get a real error message, do the following.
Setting the
Access-Control-Allow-Origin
header to
*
that resources can be accessed correctly from any domain. Y
ou can replace
*
with your domain as needed: for example,
Access-Control-Allow-Origin:www.example.com
However, dealing with multiple domains can be complex, and if using a CDN can cause caching problems, it may not be worth the effort.
Here are some examples of how to set this header in a variety of environments:
Apache
In the folder where the
JavaScript
file will be provided, create a
.htaccess
file with the following:
Header add Access-Control-Allow-Origin "*"
Nginx
Add
add_header
instructions to the
location
block that provides
JavaScript
files:
location ~ ^/assets/ {
add_header Access-Control-Allow-Origin *;
}
HAProxy
Add the following to the
asset
backend that provides
JavaScript
files:
rspadd Access-Control-Allow-Origin:\ *
In your
HTML
source code, for each script on which you set the
Access-Control-Allow-Origin
header, set
crossorigin="anonymous"
on the
script
tag. B
efore you add the
crossorigin
property to the
script
tag, make sure that you have verified that a header has been sent to the script file.
In
Firefox
if there is a
crossorigin
property and there is no
Access-Control-Allow-Origin
header, the script is not executed.
This is an error that occurs in the IE, which you can test in the IE developer console when you call the
undefined
method.
This is equivalent to the error "TypeError: 'undefined' is not a function" in Chrome. Yes, different browsers may have different error messages for the same logical error.
This is a common problem for IE in Web applications with
JavaScript
namespaces, in which case 99.9% of the problem is that IE cannot bind methods in the current namespace to
this
keyword.
For example, if your JS namespace
Rollbar
uses the
isAwesome
method.
In general, if you are in the
Rollbar
namespace, you can call the
isAwesome
method using the following syntax:
this.isAwesome();
Chrome, Firefox and Opera will be happy to accept this syntax. I
E, on the other hand, does not.
Therefore, when using
JS
namespace, the safest way is to prefix the actual namespace.
Rollbar.isAwesome();
This is an error that occurs in Chrome when you call a function of
undefined
You can test this in the Chrome Developer Console and
Mozilla Firefox
Developer Console.
As
JavaScript
coding techniques and design patterns have become more complex over the years, so have the scope of self-references in callbacks and closures, which is a fairly common source of this or that confusion.
Consider the following sample snippet:
function clearBoard(){
alert("Cleared");
}
document.addEventListener("click", function(){
this.clearBoard(); // 这个 "this" 是什么?
});
If you execute the above code and then click the page, it will result in the following error, "Uncaught TypeError: this.clearBoard not a function".
The reason is that the anonymous function being executed is in the context of the document, and
clearBoard
is defined in
window
The traditional, browser-compatible solution is simply to save its reference in a variable, and then close the package to inherit the variable. For example:
var self = this;
document.addEventListener("click", function(){
self.clearBoard();
});
In addition, in newer browsers, you can use
bind()
method to pass the correct reference:
document.addEventListener("click",this.clearBoard.bind(this));
This is an error that Chrome has made in several cases, one of which is to call a recursive function that does not terminate. You can test this in the Chrome Developer Console.
This can also happen if you pass a value to a function that is out of range.
The input values of many functions accept only a specific range of numbers, for example,
Number.toExponential(digits)
and
Number.toFixed(digits)
accept numbers between 0 and 20, while
Number.toFixed(digits)
accept numbers between 1 and 21.
var a = newArray(4294967295); //OK
var b = newArray(-1); //range error
var num = 2.555555;
document.writeln(num.toExponential(4)); //OK
document.writeln(num.toExponential(-2)); //range error!
num = 2.9999;
document.writeln(num.toFixed(2)); //OK
document.writeln(num.toFixed(25)); //range error!
num = 2.3456;
document.writeln(num.toPrecision(1)); //OK
document.writeln(num.toPrecision(22)); //range error!
This is an error in Chrome because you can test it in the Chrome developer console by reading the
length
property of the
undefined
variable.
Typically, you can find the defined length on the array, but if the array is not initialized or the variable name is hidden in another context, you may encounter this error. Let us know about this error with the following example.
var testArray= ["Test"];
function testFunction(testArray) {
for (var i = 0; i < testArray.length; i++) {
console.log(testArray[i]);
}
}
testFunction();
When you declare a function with arguments, they become local arguments.
This means that even if you have a variable with the name
testArray
arguments with the same name within the function will still be treated as local arguments.
You can solve the problem in two ways:
Remove the arguments in the function declaration statement (it turns out that you want to access variables that are declared outside the function, so you don't need to use parameters for the function)
var testArray = ["Test"];
/* 前置条件:在函数外部定义testArray */
function testFunction(/* No params */) {
for (var i = 0; i < testArray.length; i++) {
console.log(testArray[i]);
}
}
testFunction()
Call the function and pass it the array we declared.
var testArray = ["Test"];
function testFunction(testArray) {
for (var i = 0; i < testArray.length; i++) {
console.log(testArray[i]);
}
}
testFunction(testArray);
When we try to access an undefined variable, it always
undefined
and we cannot get or set any
undefined
properties.
In this case, the application raises the Uncaught TypeError:Cannot set property.
For example, in Chrome:
If
test
object does not exist, the error raises Uncaught TypeError:Cannot set property.
This error is raised when you try to access
undefined
or variable that is outside the current range.
You can test it very easily in Chrome.
If you receive this error while using the event processing system, make sure that you use the incoming event object as an argument. O lder browsers, such as IE, provide global variable events, and Chrome automatically attaches event variables to handlers. F irefox doesn't automatically add it. Libraries such as jQuery try to regulate this behavior, but nevertheless, it is best to use the method passed to the event handler function.
document.addEventListener("mousemove", function (event) {
console.log(event);
})
As it turns out, many of them are
null
or
undefined
errors. I
f you use strict compiler options, static type checking systems like
Typescript
can help you avoid using them.
It can warn you if a type is expected, but has not yet been defined.
Here's a look at the
10 classic questions
about JavaScript errors from
W3Cschool编程狮