1. Uncaught TypeError: Cannot read property
如果你是一个javascript开发者,你肯定看到过此错误
读取属性或调用方法的对象的未定义
这可能由于许多原因而发生,但常见的是在呈现UI组件时不正确地初始化状态。 让我们看一个在真实应用程序中如何发生这种情况的示例。 我们将选择React,但不正确初始化的相同原则也适用于Angular,Vue或任何其他框架。
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>
);
}
}
这里有两个重要的事情:
组件的状态(例如this.state)以未定义的形式开始。 当您异步获取数据时,组件将在加载数据之前至少呈现一次 - 无论是在构造函数,componentWillMount还是componentDidMount中获取它。 当测验首次渲染时,this.state.items未定义。 反过来,这意味着ItemList将项目定义为未定义,并且您在控制台中收到错误 - “Uncaught TypeError:无法读取未定义的属性’map’”。
这很容易解决。 最简单的方法:在构造函数中使用合理的默认值初始化状态。
class Quiz extends Component {
// Added this:
constructor(props) {
super(props);
// Assign state itself, and a default value for items
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>
);
}
}
2 TypeError: ‘undefined’ is not an object
3TypeError: null is not an object
有趣的是,在JavaScript中,null和undefined不一样,这就是为什么我们看到两个不同的错误消息。 未定义通常是尚未分配的变量,而null表示该值为空。 要验证它们不相等,请尝试使用严格相等运算符:
在现实世界的示例中,这种错误的一种方式是,如果在加载元素之前尝试在JavaScript中使用DOM元素。 这是因为对于空白的对象引用,DOM API返回null。
任何执行和处理DOM元素的JS代码都应该在创建DOM元素之后执行。 JS代码按照HTML中的布局从上到下进行解释。 因此,如果DOM元素之前有标记,则脚本标记中的JS代码将在浏览器解析HTML页面时执行。 如果在加载脚本之前尚未创建DOM元素,则会出现此错误。
在此示例中,我们可以通过添加一个事件侦听器来解决此问题,该事件侦听器将在页面准备就绪时通知我们。 一旦触发了addEventListener,init()方法就可以使用DOM元素。
<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>
4 (unknown): Script error
当未捕获的JavaScript错误跨越域边界而违反跨源策略时,会发生脚本错误。 例如,如果您在CDN上托管JavaScript代码,任何未捕获的错误(冒泡到window.onerror处理程序的错误,而不是在try-catch中捕获)将被报告为“脚本错误”而不是包含有用的错误 信息。 这是一种浏览器安全措施,旨在防止跨域传递数据,否则将无法进行通信。
要获取真实的错误消息,请执行以下操作:
1.发送Access-Control-Allow-Origin标头
将Access-Control-Allow-Origin标头设置为表示可以从任何域正确访问资源。 如有必要,您可以用您的域替换:例如,Access-Control-Allow-Origin:www.example.com。 但是,处理多个域变得棘手,如果您因使用可能出现的缓存问题而使用CDN,则可能不值得付出努力。 在这里查看更多。
以下是有关如何在各种环境中设置此标头的一些示例:
Apache
在将从中提供JavaScript文件的文件夹中,使用以下内容创建.htaccess文件:
Header add Access-Control-Allow-Origin "*"
Nginx
将add_header指令添加到为JavaScript文件提供服务的位置块:
location ~ ^/assets/ {
add_header Access-Control-Allow-Origin *;
}
HAProxy
将以下内容添加到资源后端,其中提供JavaScript文件:
rspadd Access-Control-Allow-Origin:\ *
5. TypeError: Object doesn’t support property
当您调用未定义的方法时,这是在IE中发生的错误。 您可以在IE Developer Console中对此进行测试。
这相当于Chrome中的错误“TypeError:’undefined’不是函数”。 是的,不同的浏览器可以针对相同的逻辑错误具有不同的错误消息。
对于使用JavaScript命名空间的Web应用程序中的IE,这是一个常见问题。 在这种情况下,99.9%的问题是IE无法将当前命名空间中的方法绑定到this关键字。 例如,如果您使用方法isAwesome的JS名称空间Rollbar。 通常,如果您在Rollbar名称空间内,则可以使用以下语法调用isAwesome方法:
this.isAwesome();
Chrome,Firefox和Opera很乐意接受这种语法。 另一方面,IE不会。 因此,使用JS命名空间时最安全的选择是始终使用实际命名空间作为前缀。
Rollbar.isAwesome();
6. TypeError: ‘undefined’ is not a function
7. Uncaught RangeError
这是在几种情况下Chrome中发生的错误。 一种是当你调用一个不终止的递归函数时。 您可以在Chrome开发者控制台中对此进行测试。
8. TypeError: Cannot read property ‘length’
您通常会在数组中找到定义的长度,但如果未初始化数组或者在另一个上下文中隐藏变量名,则可能会遇到此错误。 让我们通过以下示例理解此错误。
var testArray= ["Test"];
function testFunction(testArray) {
for (var i = 0; i < testArray.length; i++) {
console.log(testArray[i]);
}
}
testFunction();
9. Uncaught TypeError: Cannot set property
当我们尝试访问未定义的变量时,它总是返回undefined,我们无法获取或设置undefined的任何属性。 在这种情况下,应用程序将抛出“Uncaught TypeError无法设置未定义的属性”。
10. ReferenceError: event is not defined
当您尝试访问未定义或超出当前范围的变量时,将引发此错误。 您可以在Chrome浏览器中轻松测试它。
document.addEventListener("mousemove", function (event) {
console.log(event);
})
结论
事实证明,很多这些都是空或未定义的错误。如果使用strict编译器选项,一个好的静态类型检查系统(如Typescript)可以帮助您避免它们。如果预期类型但尚未定义,它可以警告您。即使没有Typescript,在使用它们之前使用guard子句来检查对象是否未定义也是有帮助的。