Top 10 JavaScript mistakes in 1000+ projects and how to avoid them

 

 By counting more than 1000 items in the database, we found that there are 10 most common mistakes in JavaScript. The following will explain why these errors occur and how to prevent them.

The number of occurrences of these errors is calculated from the data collected. Rollbar  collects all errors in each project and summarizes the number of times each error occurred, then groups by the characteristics of each error.

Below is a list of the top 10 most frequent JavaScript errors:

 

 

Let's begin by diving into what happens to each error in order to determine what caused it and how to avoid it.

 

1.   Uncaught TypeError: Cannot Read Property

This is the most common mistake JavaScript developers encounter. This error is reported in Chrome when you read a property or call a method on an undefined object.

There are a number of reasons for this error, a common one being incorrect initialization of state when rendering UI components. Let's look at an example of this happening in a real application.

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>
    );
  }
}

There are two important aspects of the above code:

  1. One is the state of the component (eg this.state), which is undefined until the lifecycle begins.
  2. The second is that when data is acquired asynchronously, whether in componentWillMount in the constructor or in componentDidMount extracted in the constructor, the component will be rendered at least once before the data is loaded. When detecting the first render, it will be found that this.state.items is undefined. At this point an error occurs - "Uncaught TypeError: Cannot read property 'map' of undefined" in the consol".

The fix is ​​simple: use sensible defaults for state initialization in the constructor.

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 (evaluating...)

This is an error in Safari when reading a property or calling a method on an undefined object, which is basically the same error above as Chrome, except that Safari uses a different error message.

 

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

This is an error when reading a property or calling a method on an empty object in Safari.

Interestingly, in JavaScript, null and undefined are two different types, which is why there are two different error messages. Undefined is usually a variable that has not been assigned, while null means the value is empty. To verify that they are not equal, use the strict equality operator:

In practice, one of the reasons for this error is trying to use a DOM element in JavaScript before the element is loaded. This is because the DOM API returns null for empty object references.

Any JS code that executes and processes a DOM element should be executed after the DOM element is created. JS code is interpreted top-down as specified in HTML. Therefore, if there is a tag before the DOM element, the JS code inside the script tag is executed when the browser parses the HTML page. This error occurs if the DOM element has not been created before the script is loaded.

In this example, we can fix this by adding an event listener that will notify us when the page is ready. Once addEventListener is fired, the init( ) method can use the 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>

 

4. (unknown): Script Error

Script errors occur when uncaught JavaScript errors violate the cross-boundary principle. For example, if the JavaScript code is hosted on a CDN, any uncaught errors (those issued by the window.onerror handler, not those caught in try-catch) will only be reported as "script errors". This is a security measure of the browser, mainly used to prevent the occurrence of cross-domain transfer of data.

To get the real error message, you need to do the following:

1.    Access-Control-Allow-Origin

Set Access-Control-Allow-Origin to *, which means the resource can be properly accessed from any domain. * If necessary, you can also replace it with your own domain name, for example:

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

Here are some examples of settings in various environments:

Apache

In the JavaScript folder, create a .htaccess file with the following content:

Header add Access-Control-Allow-Origin "*"

Nginx

Add the add_header directive to the location block that serves the JavaScript file:

location ~ ^/assets/ {
    add_header Access-Control-Allow-Origin *;
}

HAProxy

Add the following to the static resource configuration backend that serves JavaScript files:

rspadd Access-Control-Allow-Origin:\ *

2.     Set crossorigin="anonymous" on the script tag

In your HTML source, set Access-Control-Allow-Origin for each script, and in the Set SCRIPT tag, set crossorigin="anonymous". Before adding the crossorigin attribute to the script tag, make sure that the header is being sent to the script file. In Firefox, if the crossorigin attribute is present but the Access-Control-Allow-Origin header is not present, the script will not execute.

 

5. TypeError: Object Doesn’t Support Property

Such an error occurs in IE when an undefined method is called.

This is equivalent to the "undefined' is not a function" error in Chrome. Different browsers may have different error messages for the same logic error.

This is a common problem with using JavaScript namespaces in IE web applications. The vast majority of the reason this happens is that IE cannot bind methods in the current namespace to the this keyword. For example, if you have the namespace isAwesome for the JS Rollbar method. Typically, if inside the Rollbar namespace, the isAwesome method can be called using the following syntax:

this.isAwesome();

Chrome, Firefox and Opera accept this syntax, IE does not. So the safest thing to do when using JS namespaces is to always prefix with the actual namespace.

Rollbar.isAwesome();

 

6. TypeError: ‘undefined’ Is Not a Function

Such an error occurs in Chrome when calling an undefined function.

As JavaScript coding techniques and design patterns have become more complex over the past few years, the corresponding increase in self-referential scope in callbacks and closures is a major source of this confusion.

As in the sample code snippet below:

function testFunction() {
  this.clearLocalStorage();
  this.timer = setTimeout(function() {
    this.clearBoard();    // what is "this"?
  }, 0);
};

Executing the above code will result in the following error: "Uncaught TypeError: undefined is not a function." The reason for the above error is that when you call setTimeout( ), you are actually calling window.setTimeout( ), which is passed to setTimeout( ) is defined in the context of the window object, which does not have a clearBoard( ) method.

A solution compliant with older browsers is to simply store the reference in this in a variable and then inherit through a closure. E.g:

function testFunction () {
  this.clearLocalStorage();
  var self = this;   // save reference to 'this', while it's still this!
  this.timer = setTimeout(function(){
    self.clearBoard();  
  }, 0);
};

Or, in newer browsers, pass the reference using the bind( ) method:

function testFunction () {
  this.clearLocalStorage();
  this.timer = setTimeout(this.reset.bind(this), 0);  // bind to 'this'
};
function testFunction(){
    this.clearBoard();    //back in the context of the right 'this'!
};

 

7. Uncaught RangeError: Maximum Call Stack

This is a bug that occurs in many cases, Chrome, one case is when you call a recursive function that doesn't terminate.

This can also happen if a value is passed to a function that is out of scope. Many functions only accept numeric input values ​​within a certain range. For example, Number.toExponential( digits ) and Number.toFixed( digits ) accept arguments ranging from 0 to 20, while Number.toPrecision( digits ) accepts numbers ranging from 1 to 21.

var a = new Array(4294967295);  //OK
var b = new Array(-1); //range error
var num = 2.5555555;
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!

 

8. TypeError: Cannot Read Property ‘length’

This is an error that occurs in Chrome because a variable with undefined length property is read.

Usually the defined length can be found in an array, but this error can occur if the array is uninitialized or if the variable name is hidden in another context. Let us explain this kind of 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 a function is declared with parameters, those parameters become local parameters. This means that even if you have a variable with the name testArray, a parameter with the same name in the function will still be treated as a local parameter .

There are two ways to solve this problem:

1. Remove the parameter in the function declaration statement:

var testArray = ["Test"];
/* Precondition: defined testArray outside of a function */
function testFunction(/* No params */) {
        for (var i = 0; i < testArray.length; i++) {
              console.log(testArray[i]);
        }
}
testFunction();

2. Call the array function passed to our declaration:

var testArray = ["Test"];
function testFunction(testArray) {
for (var i = 0; i < testArray.length; i++) {
        console.log(testArray[i]);
        }
}
testFunction (testArray);

 

9. Uncaught TypeError: Cannot Set Property

When trying to access an undefined variable, undefined is always returned. We also cannot get or set any properties of undefined. In this case, the application will throw "Uncaught TypeError cannot set property of undefined".

For example, in the Chrome browser, if the test object does not exist, this error occurs:

So you need to define the variable before accessing the variable.

 

10. ReferenceError: Event Is Not Defined

This error is raised when trying to access an undefined variable or a variable outside the current scope.

 

If you encounter this error when using the event handling system, make sure to use the event object passed in as a parameter. Browsers like IE provide global variable events, Chrome automatically attaches event variables to handlers, Firefox does not.

document.addEventListener("mousemove", function (event) {
  console.log(event);
})

 

Recommended JavaScript development tools

SpreadJS pure front-end table control is an HTML5-based JavaScript spreadsheet and grid function control, providing a complete formula engine, sorting, filtering, input controls, data visualization, Excel import/export and other functions, suitable for .NET, Java and mobile Table program development for online editing of Excel-like functions on various platforms such as the terminal.

 

in conclusion

It turns out that many of these null or undefined errors are common. A good static type checking system like Typescript, when set to strict compile options, can help developers avoid these errors.

Finally, I hope that this article can help developers better avoid or deal with the above 10 mistakes.

Original link: https://dzone.com/articles/top-10-javascript-errors-from-1000-projects-and-ho-1

Please indicate the source of the reprint: Grape City Controls

 

About Grape City

Founded in 1980, Grape City is the world's leading software and service provider integrating development tools, business intelligence solutions, and management system design tools. Xi'an Grape City is its branch in China, providing software R&D services to the global market, and international advanced development tools, software and R&D consulting services for the informatization of Chinese enterprises.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326113088&siteId=291194637