10 _javascript tips for making small mistakes in JavaScript

Source: Internet
Author: User

Today, JavaScript has become the centerpiece of Web page editing. Especially in the past few years, the Internet has witnessed the emergence of a large number of JS libraries in the areas of spa development, graphic processing, and interaction.

If you deal with the first time, many people will find JS very simple. Indeed, for many experienced engineers, or even beginners, there is almost no obstacle to achieving basic JS functionality. But the real function of JS is more diverse and complex than many people think. Many of the details of JavaScript will make your Web page a lot of unexpected bugs, understand these bugs, to become an experienced JS developer is very important.

Common error One: Incorrect references to this keyword

I once heard a comedian say:

"I've never been here, because I don't know where this is, except for the place out there?" ”

This phrase is more or less a metaphor for the developers in the JS development of this keyword use error. What does this refer to? Is it the meaning of this in everyday spoken english?

With the continuous complication of JS programming in recent years, functional diversification, for a program structure of internal guidance, reference also gradually become more

Let's take a look at this piece of code here:

Game.prototype.restart = function () {  this.clearlocalstorage (); 

  This.timer = settimeout (function () {   this.clearboard ();    }, 0);

 

Running the above code will cause the following error:

Uncaught typeerror:undefined is not a function
Why is that? The call to this is closely related to the environment in which it resides. The above error occurs because when you call the settimeout () function, you actually call Window.settimeout (). Therefore, the function defined in settimeout () is actually defined in the window context, and there is no Clearboard () method in the window.

There are two solutions available below. The first simpler and more straightforward approach is to store this in a variable so that he can be inherited in a different context:

Game.prototype.restart = function () {  this.clearlocalstorage (); 

  var self = this;

  This.timer = settimeout (function () {   self.clearboard ();}, 0);

  The second approach is to use the bind () method, but this is a bit more complicated than the previous one.

Game.prototype.restart = function () {  this.clearlocalstorage (); 

  This.timer = settimeout (This.reset.bind (this), 0); };   

Game.prototype.reset = function () {   this.clearboard ();};

In the example above, two this refers to Game.prototype.

Common mistakes Two: The life cycle misunderstanding of traditional programming language

Another error that is easy to make is to take the thought of other programming language, think in JS, also exist life cycle so say. Take a look at the following code:

for (var i = 0; i < i++) {  /* ... */} console.log (i);

If you think you're going to report a undefined error when running Console.log (), you're wrong. I will tell you that it will actually return 10.

Of course, in many other languages, encountering such code will certainly be an error. Because I have obviously transcended its life cycle. The variable defined in for is the end of the loop, and its life is over. But in JS, I's life will continue. This phenomenon is called variable hoisting.

And if we want to implement variables that have a lifecycle in a particular logic module like any other language, we can use the Let keyword.

Common errors three: memory leaks

Memory leaks in JS become almost an unavoidable problem. If not particularly careful, in the final inspection process, there will be a variety of memory leakage problems. Let's take a look at the following examples:

var thething = null; 

var replacething = function () {  

    var priorthing = thething; 

    var unused = function () { 

         if (priorthing) {    console.log ("Hi");   }  

    ; 

    thething = {   longstr:new Array (1000000). Join (' * '),// 

         somemethod:function () {    Console.log (somemessage );   }  
    }; 
};  
SetInterval (replacething, 1000); 

If you run the above code, you will find that you have caused a lot of memory leaks, leaking 1M of memory per second, and obviously the GC (garbage collector) is not going to help you. From the code above, it seems that longstr is not recycled at every replacething call. What is this for?

Each thething structure contains a list of LONGSTR structures. Every second, when we call replacething, it passes the current point to priorthing. But here we will also see that there is no problem, because priorthing every time is to unlock the last function of the point before accepting the new assignment. And all of this is happening in the replacething function body, according to the common sense when the function body is finished, the local variables in the function will be collected by GC, there will be no memory leakage problem, but why the above error?

This is because the definition of LONGSTR is done in a closure, and it is referenced by other closures, JS rules that when the closure is introduced to a variable outside the closure, the object cannot be garbage collected when the closure ends (GC).

Common errors four: comparison operators

One of the more convenient places in JavaScript is that it can force the conversion of the result variable into a Boolean type for each comparison operation. But on the other hand, sometimes it brings us a lot of inconvenience, and the following examples are code instances that have plagued many programmers:

Console.log (false = = ' 0 '); 

Console.log (null = = undefined); 

Console.log ("\t\r\n" = 0); 

Console.log (' = = 0); And these do too! 

if ({})//... 

if ([])//... 

The last two lines of code are null (often mistaken for false), but in fact either {} or [] is an entity class, and any class actually converts to true. As these examples show, some types of forced conversions are very vague. Therefore, many times we prefer to use = = = and!== to replace = = and!=, in order to avoid forced type conversion. The use of = = = and!== is the same as before = = and!=, except that they do not occur type casts. It is also important to note that when any value is compared to NaN, even including himself, the result is false. Therefore, we cannot use simple comparison characters to determine whether a value is NaN. We can use the built-in isNaN () function to identify:

Console.log (nan = = nan);  False 

Console.log (nan = = nan);  False 

Console.log (isNaN (NaN));  True 

Common errors Five: inefficient DOM operations

The DOM basic operation in JS is very simple, but how to effectively do these operations has always been a problem. One of the most typical problems is adding DOM elements in batches. Adding a DOM element is a much more expensive operation. And the bulk of the increase in the cost of the system is even more expensive. A better way to bulk increase is to use document fragments:

var div = document.getelementsbytagname ("My_div"); 

var fragment = Document.createdocumentfragment (); 

 for (var e = 0; e < elems.length; e++) {fragment.appendchild (elems[e]); Div.appendchild (true); 

Adding a DOM element directly is a very expensive operation. But it's much more efficient to create all the elements that you want to add, and then add them all up.

Common error Six: Incorrect function call in the FOR loop

Please look at the following code:

var elements = document.getelementsbytagname (' input ');

var n = elements.length; 

for (var i = 0; i < n; i++) {   

Elements[i].onclick = function () {     

Console.log ("The IS element #" + i);   }; } 

Run the above code, if there are 10 buttons on the page, click on each button will pop up "This is element #10"!. This is not the same as we originally expected. This is because when the click event is triggered, the for loop has already been executed and the value of I has changed from 0.

We can use the following code to achieve the really correct effect:

var elements = document.getelementsbytagname (' input '); 

var n = elements.length; 

var makehandler = function (num) {//outer function return

   function () { 

Console.log ("It is element #" + num); 
   }; }; 

for (var i = 0; i < n; i++) 

{   Elements[i].onclick = Makehandler (i+1);} 

In this version of the code, Makehandler is executed immediately at every loop, passing i+1 to the variable num. The outside function returns the function inside, and the Click event function is set to the inside function. So that each trigger function is able to use the correct I value.

Common errors Seven: prototype inheritance issues

A large part of the JS developers can not fully grasp the prototype inheritance problem. Here is an example to illustrate:

Baseobject = function (name) {   

if (typeof name!== "undefined") 

{     this.name = name;   } 

else 

{     this.name = ' Default '   }}; 

This piece of code looks very simple. If you have a name value, use it. If not, use ' default ':

var firstobj = new Baseobject (); 

var secondobj = new Baseobject (' unique '); 

Console.log (Firstobj.name); -> result is ' default ' 

console.log (secondobj.name);//-> result is ' unique ' 

But what if we execute the DELETE statement:

Delete Secondobj.name;
we will get:

Console.log (Secondobj.name); -> result is ' undefined '
But wouldn't it be better if you could go back to ' default '? In fact, to achieve this effect is very simple, if we can use the prototype inheritance:

Baseobject = function (name) 

{   if (typeof name!== "undefined") 

{     this.name = name;   }}; 

BaseObject.prototype.name = ' default '; 

In this release, Baseobject inherits the name attribute in the prototype and is set to ' default '. At this point, if the constructor is invoked without arguments, it is automatically set to default. Similarly, if the Name property is removed from the Baseobject, the system will automatically look for the prototype chain and get the ' default ' value:

 var thirdobj = new Baseobject (' unique '); 

 Console.log (thirdobj.name); 

 Delete Thirdobj.name;

 Console.log (Thirdobj.name); -> result is ' default ' 

Common errors Eight: Create an error guide for an instance method

Let's look at the following code:

var MyObject = function () {} 

 MyObject.prototype.whoAmI = function () {   

Console.log (this = = window?) "Window": "MyObj"); }; 

 var obj = new MyObject (); 

Now for the sake of convenience, we create a new variable to direct the WhoAmI method, so we can use WhoAmI () instead of longer obj.whoami ():

var WhoAmI = Obj.whoami;
Next, to make sure everything is going as we predicted, we can print out the WhoAmI:

Console.log (WhoAmI);
The result:

function () {   Console.log (this = = window?) "Window": "MyObj"); } 

No mistakes!

But now let's look at two ways of referencing:

Obj.whoami (); Output "MyObj" (as expected) 

WhoAmI ();   Output "Window" (uh-oh!) 

Where did it go wrong?

The principle is actually the same as the second common error above, when we execute var whoAmI = Obj.whoami, the new variable WhoAmI is defined in the global context. So it's this is referring to window, not obj!

The correct encoding method should be:

var MyObject = function () {} 

MyObject.prototype.whoAmI = function () {   

   Console.log (this = = window?) "Window": "MyObj"); }; 

var obj = new MyObject (); 

OBJ.W = Obj.whoami;  Still in the Obj namespace Obj.whoami (); Output "MyObj" (as expected) 

OBJ.W ();    Output "MyObj" (as expected) 

Common error Nine: use a string as the first argument for settimeout or setinterval

First we have to declare that there is no grammatical error with the string as the first argument of the two functions. But this is actually a very inefficient approach. Because from a system perspective, when you use a string, it is passed into the constructor and the other function is called again. This slows down the progress of the program.

SetInterval ("LogTime ()", 1000); 

SetTimeout ("logmessage (' + Msgvalue +") ", 1000); 

Another approach is to pass functions as arguments directly:

SetInterval (LogTime, 1000);  

settimeout (function () { 

logmessage (msgvalue);}, 1000); 

Common error Ten: ignore the role of "strict mode"

"Strict Mode" is a more rigorous code-checking mechanism and makes your code more secure. Of course, not choosing this pattern doesn't mean it's a mistake, but using this pattern will make sure your code is more accurate.

Below we summarize a few "strict mode" Advantages:

1. Make debug easier: Many errors are overlooked in normal mode, and the "strict mode" mode will make debug extremes more rigorous.

2. Prevent default global variables: In normal mode, giving a declared variable the name will automatically set the variable to global. In strict mode, we canceled this default mechanism.

3. Cancel the default conversion of this: in normal mode, giving the This keyword to null or undefined will make it automatically converted to global. In strict mode, we canceled this default mechanism.

4. Prevent duplicate variable declarations and parameter declarations: variable declarations that are duplicated in strict mode are held incorrectly, such as (e.g., var object = {foo: "Bar", Foo: "Baz"};) Also, repeated use of the same parameter name in a function declaration can be an error, such as (e.g., function foo (val1, Val2, Val1) {}).

5. Make the Eval () function more secure.

6. When encountered invalid delete instruction after the error: Delete instructions can not be implemented in the class, in the normal case of this situation is silently ignored, and in the strict mode is the error.

As with other technical languages, the more you know about JavaScript, the more you know how it works, and why it works, you will be proficient in mastering and using the language. Conversely, if you lack the knowledge of JS mode, you will encounter a lot of problems. Understanding some of the details of JS syntax or features will help you improve the efficiency of programming, reduce the problems encountered.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.