精品推荐:大神总结的十大 JavaScript 错误及如何规避

双子孤狼 2018-09-07 13:57:27 ⋅ 559 阅读

英文:Jason Skowronski   译文:葡萄城控件

www.cnblogs.com/powertoolsteam/p/top-10-javascript-errors.html


通过统计数据库中的1000多个项目,我们发现在 JavaScript 中最常出现的错误有10个。下面会向大家介绍这些错误发生的原因以及如何防止。


对于这些错误发生的次数,我们是通过收集的数据统计得出的。Rollbar 会收集每个项目中的所有错误,并总结每个错误发生的次数,然后通过各个错误的特征进行分组。


下图是发生次数最多的10大 JavaScript 错误:


 


下面开始深入探讨每个错误发生的情况,以便确定导致错误发生的原因以及如何避免。

 

1.   Uncaught TypeError: Cannot Read Property


这是 JavaScript 开发人员最常遇到的错误。当你读取一个属性或调用一个未定义对象的方法时,Chrome 中就会报出这样的错误。



导致这个错误发生的原因有很多,常见的一种情况是在渲染 UI 组件时,不正确地初始化状态。我们来看一个真实的应用程序中发生这种情况的例子。



以上代码有两个重要方面:


  1. 一是组件的状态(例如 this.state),在开始生命周期之前是 undefined 状态。

  2. 二是当通过异步的方式获取数据时,无论是在构造函数中 componentWillMount 中,还是在构造函数中提取 componentDidMount,组件在数据加载之前至少会渲染一次。当检测首次渲染时,会发现 this.state.items 是未定义的。此时就会出现一个错误 -“Uncaught TypeError: Cannot read property ‘map’ of undefined" in the consol”。


解决的方法很简单:在构造函数中使用合理的默认值进行状态初始化。



2. TypeError: ‘undefined’ Is Not an Object (evaluating...)


这是在 Safari 中读取属性或调用未定义对象上的方法时发生的错误,这与 Chrome 的上述错误基本相同,只是 Safari 使用不同的错误消息。


 

3. TypeError: Null Is Not an Object (evaluating...)


这是在 Safari 中读取属性或调用空对象上的方法时发生的错误。



有趣的是,在 JavaScript 中,null 和 undefined 是两种不同的类型,这就是为什么会出现两个不同的错误消息。未定义通常是一个尚未分配的变量,而 null 则表示该值为空。要验证它们不相等,请使用严格的相等运算符:



在实际情况中,导致这种错误的原因之一是:在元素加载之前,就尝试在 JavaScript 中使用 DOM 元素。这是因为 DOM API 对于空白的对象引用返回 null。


任何执行和处理 DOM 元素的 JS 代码,都应该在创建 DOM 元素之后执行。JS 代码按照 HTML 中的规定自上而下进行解释。因此,如果在 DOM 元素之前存在标签,则脚本标签内的 JS 代码就会在浏览器分析 HTML 页面时执行。如果在加载脚本之前尚未创建 DOM 元素,就会出现这样的错误。


在这个例子中,我们可以通过添加一个事件侦听器来解决这个问题,事件侦听器会在页面准备就绪时通知我们。一旦 addEventListener 被触发,该 init(  ) 方法就可以使用 DOM 元素。



4. (unknown): Script Error


当未捕获的 JavaScript 错误违背跨边界原则时,就会发生脚本错误。例如,如果将 JavaScript 代码托管在 CDN 上,则任何未被捕获的错误(通过 window.onerror 处理程序发出的错误,而不是 try-catch 中捕获到的错误)将仅报告为“脚本错误”。这是浏览器的一种安全措施,主要用于防止跨域传递数据的情况出现。


要获取真实的错误消息,需要执行以下操作:


Access-Control-Allow-Origin


将 Access-Control-Allow-Origin 设置为 *, 表示可以从任何域正确访问资源。* 如有必要,也可以用自己的域名进行替换,例如:


Access-Control-Allow-Origin: www.example.com。


以下是在各种环境中设置的一些示例:


  • Apache


在 JavaScript 文件夹中,创建一个 .htaccess 文件,并包含以下内容:



  • Nginx


将 add_header 指令添加到提供 JavaScript 文件的 location block 中:



  • HAProxy


将以下内容添加到提供 JavaScript 文件的静态资源配置后端:



在脚本标签上设置crossorigin =“anonymous”


在你的 HTML 源代码中,为每一个脚本设置 Access-Control-Allow-Origin,在设置 SCRIPT 标签中,设置 crossorigin="anonymous"。在将 crossorigin 属性添加到脚本标签之前,请确保正在向脚本文件发送 header。在 Firefox 中,如果 crossorigin 属性存在但 Access-Control-Allow-Origin 标题不存在,则脚本不会执行。

 

5. TypeError: Object Doesn’t Support Property


当调用未定义的方法时,IE 中会发生这样的错误。



这相当于 Chrome 中的 “undefined’ is not a function” 错误。对于相同的逻辑错误,不同的浏览器可能会有不同的错误消息。


这是在 IE 的 Web 应用程序中使用 JavaScript 命名空间出现的一个常见问题。出现这种情况的绝大部分原因是IE无法将当前名称空间内的方法绑定到this关键字。例如,如果你有 JS Rollbar 方法的命名空间 isAwesome。通常,如果位于 Rollbar 命名空间内,则可以使用以下语法调用该 isAwesome 方法:



Chrome、Firefox 和 Opera 接受这种语法,IE则不接受。因此,使用 JS 命名空间时最安全的做法是:始终以实际名称空间作为前缀。



6. TypeError: ‘undefined’ Is Not a Function


当调用未定义的函数时,Chrome 中就会发生这样的错误。


随着 JavaScript 编码技术和设计模式在过去几年中变得越来越复杂,回调和闭包中的自引用范围也相应增加,这是造成这种混乱现象的主要来源。


正如下面的示例代码片段:



执行上面的代码会导致以下错误:“Uncaught TypeError: undefined is not a function。” 发生以上错误的原因是,当你调用 setTimeout(  )  时,实际上是在调用 window.setTimeout(  ),传递给 setTimeout(  ) 的匿名函数是在窗口对象的上下文中定义的,而该窗口对象没有 clearBoard(  ) 方法。


符合旧版浏览器的解决方案是以变量的方式简单地将引用保存在 this 中,然后通过闭包继承。例如:



或者,在较新的浏览器中,使用 bind(  ) 方法传递引用:

 


7. Uncaught RangeError: Maximum Call Stack


这是在很多种情况,Chrome 中发生的错误,一种情况是当你调用一个不会终止的递归函数时。



如果将值传递给超出范围的函数,也可能会发生这种情况。许多函数只接受特定范围内的数字输入值。例如,Number.toExponential( digits ) 与 Number.toFixed( digits) 接受的参数范围为从0到20,而 Number.toPrecision( digits ) 接受的数字范围为从1至21。



8. TypeError: Cannot Read Property ‘length’


这是 Chrome 中发生的错误,因为读取了未定义长度属性的变量。



通常在数组中能够找到定义的长度,但是如果数组未初始化或变量名在另一个上下文中隐藏,则可能会出现这种错误。让我们用下面的例子来解释这种错误。



当用参数声明一个函数时,这些参数会成为本地参数。这意味着即使你有名称变量 testArray,函数中具有相同名称的参数仍会被视为本地参数。


有两种方法可以解决这个问题:


1. 删除函数声明语句中的参数:



2. 调用传递给我们声明的数组函数:



9. Uncaught TypeError: Cannot Set Property


当尝试访问未定义的变量时,总会返回 undefined。我们也无法获取或设置 undefined 的任何属性。在这种情况下,应用程序将抛出“Uncaught TypeError cannot set property of undefined”。


例如,在 Chrome 浏览器中,如果 test 对象不存在,就会出现这种错误:



所以就需要在访问变量之前,对变量进行定义。

 

10. ReferenceError: Event Is Not Defined


尝试访问未定义的变量或当前范围之外的变量时会引发此错误。


 


如果在使用事件处理系统时遇到此错误,请确保使用传入的事件对象作为参数。IE 这样的浏览器提供了全局变量事件,Chrome 会自动将事件变量附加到处理程序中,Firefox 则不会自动添加事件变量。



JavaScript 开发工具推荐


SpreadJS 纯前端表格控件是基于 HTML5 的 JavaScript 电子表格和网格功能控件,提供了完备的公式引擎、排序、过滤、输入控件、数据可视化、Excel 导入/导出等功能,适用于 .NET、Java 和移动端等各平台在线编辑类 Excel 功能的表格程序开发。

 

结论


事实证明很多这些 null 或 undefined 的错误是普遍存在的。 一个类似于 Typescript 这样的好的静态类型检查系统,当设置为严格的编译选项时,能够帮助开发者避免这些错误。


最后也希望通过本文,可以帮助开发者更好避免或是应对以上的10种错误。


---------------END----------------

后续的内容同样精彩

长按关注“IT实战联盟”哦



全部评论: 0

    我有话说:

    精品推荐:一览GitHub上最受程序欢迎5Java开源项目

    列举了GitHub上一些最流行Java项目。从Mockitos到Guava,以及 java-design-patterns等供大家学习。

    精品推荐:Tomcat优化总结(实战版)

    Tomcat是我们经常使用 servlet容器之一,甚至很多线上产品都使用 Tomcat充当服务器。

    盘点2017,互联网事件

    共享经济、比特币、乐视贾跃亭、互联网独角兽和世界互联网大会等2017互联网事件

    【开源推荐】基于 Go 语言轻量级高性能日志库 logit使用测评

    logit 是一个简单易用并且是基于级别控制日志库,可以应用于所有 GoLang 应用程序中。

    总结】前端5常见设计模式,代码一看你就懂!

    用代码示例来掌握前端5设计模式

    精品推荐:nginx常用配置总结(实战版)

    Nginx (engine x) 是一个高性能HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器。

    阿里牛谈垃圾回收算法是如何设计

    前言 如果大家关注 JDK,会发现在频繁发布 JDK 版本中,和垃圾回收相关 JEP (JDK Enhancement Proposals,Java 增强提案)越来越多了,垃圾回收

    精品推荐:4个顶级开源JavaScript图表库

    图表对于可视化数据和使网站具有吸引力非常重要。可视化演示使分析块数据和传达信息变得更加容易。

    精品推荐:11个高人气Javascript动画库

    翻译 | 小生 来源 | https://www.zcfy.cc/article/11-javascript-animation-libraries-for-2018

    Docker - 数据环境快速搭建步骤

    快速搭建一个数据环境,我们可以使用Docker来实现,文章会演示如何使用。

    精品推荐如何实现一个TCC分布式事务框架一点思考

    本文将以Spring容器为例,试图分析一下,实现一个通用TCC分布式事务框架需要注意一些问题。

    精品推荐Javascript 将 HTML 页面生成 PDF 并下载

    最近碰到个需求,需要把当前页面生成 pdf并下载,有需要可以看看哦~~~

    公约数和最小公倍数

    一. 基本概念: 如果数a能被数b整除,a就叫做b倍数,b就叫做a约数。约数和倍数都表示两个整数关系,不能单独存在。 几个整数中公有约束,叫做这几个数公约数;其中最一个,叫做这几个

    小程序实战-幸运转盘

    微信小程序幸运转盘

    【实战解析】基于HBase数据存储在京东应用场景

    作者就职于京东商城京麦平台组,从事京东商家开放平台相关开发工作。热爱技术,熟悉各种常用开源框架,有丰富大型分布式系统、高并发系统开发经验。热衷于对数据研究,对Hadoop、HBase以及