JavaScrip最容易犯的十大错误及其避免方法()

JavaScript/前端
207
0
0
2024-02-25

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子句来检查对象是否未定义也是有帮助的。