"Turn" 10 JavaScript easy to make a small mistake, you a few shots?

Source: Internet
Author: User
Tags closure setinterval

Today, JavaScript has become the core 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, graphics processing, and interaction.

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

Common Error One: Incorrect reference to this keyword

I once heard a comedian say:

"I've never been here, because I don't know where it is, except where is it?" ”

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

With the continuous complication of JS programming in recent years, the functions are diversified, and the internal guidelines and references for a program structure become more and more.

Let's look at this piece of code together:

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 this? The invocation of 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 background, and there is no Clearboard () function method in window.

Two solutions are available below. The first straightforward way is to store this in a variable so that he can be inherited in a different context:

function () {  this. Clearlocalstorage ();   var  This ;      this. Timer = SetTimeout (function() {    self.clearboard ();      0);};

The second method is to use the bind () method, but this is more complicated than the previous one, for unfamiliar with bind () students can be in the Microsoft Official view of how it is used:msdn.microsoft.com/zh-cn/library/ff841995

function () {  this. Clearlocalstorage ();   this. Timer = SetTimeout (this. Reset.bind (This), 0);    function () {    this. Clearboard ();   };

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

Common mistake two: the life cycle misunderstanding of traditional programming language

Another easy mistake is to take the thinking of other programming languages and think that in JS there is also a life cycle. Take a look at the following code:

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

If you think you'll be sure to report a undefined error when you run Console.log (), you're wrong. I will tell you that it will return 10.

Of course, in many other languages, encountering such a code will definitely be an error. Because I clearly have transcended its life cycle. The variable defined in for is at 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 a variable that has a life cycle in a particular logical module like any other language, you can use the Let keyword.

Common error Three: memory leaks

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

varTheThing =NULL;varReplacething =function () {  varPriorthing =thething; varunused =function () {    if(priorthing) {Console.log ("Hi");  }  }; TheThing={longstr:NewArray (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, leakage of 1M of memory per second, obviously the GC (garbage collector) is not able to help you. From the above code, it seems that longstr is not recycled at every replacething call. What is this for?

Each of the thething structures contains a list of LONGSTR structures. Every second when we call replacething, it passes the current pointer to priorthing. But here we will also see that there is no problem, because priorthing every time it is to solve the previous function point to accept the new assignment. And all of this is happening in the replacething function body, in common sense, when the function body ends, the local variables in the function will be recycled by GC, there will be no memory leak problem, but why the above error?

This is because the definition of LONGSTR is carried out in a closure, and it is referenced by other closures, and JS specifies that when a variable outside the closure is introduced into the closure, the object cannot be garbage collected (GC) at the end of the closure. About memory leaks in JS can be viewed: http://javascript.info/tutorial/memory-leaks#memory-management-in-javascript

Common error Four: comparison operators

One of the more convenient parts of JavaScript is the ability to force each result variable in a comparison operation into a Boolean type. But on the other hand, sometimes it can bring us a lot of inconvenience, and here are some examples of code that have been bothering many programmers:

Console.log (false = = ' 0 '); Console.log (null = = undefined); Console.log ("\t\r\n" = = 0); Console.log (' = = 0); if //  If//

The last two lines of code, although the condition is judged to be null (often mistaken for false), but in fact, whether {} or [] is an entity class, and any class will actually be converted to true. As these examples show, some types of forced conversions are very vague. So many times we prefer to use = = = and!== instead of = = and! = To avoid forced type conversions. The usage of = = = and!== is the same as the previous = = and! =, except that they do not take 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);    //  = = = NaN  );   //  Console.log (IsNaN (NaN));     //
Common error Five: inefficient DOM manipulation

The DOM basic operation in JS is very simple, but how to perform these operations effectively has always been a challenge. One of the most typical problems is the bulk addition of DOM elements. Adding a DOM element is a step that takes a lot of action. And the bulk increase in the cost of the system is not expensive. A better way to increase volume 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 (Fragment.clonenode (true));

Adding DOM elements directly is a very expensive operation. But it's much more efficient to add all of the elements you want to add before you create them all.

Common error 6: Incorrect function calls in a For loop

Please look at the following code:

var elements = document.getelementsbytagname (' input '); var n = elements.length;     for (var i = 0; i < n; i++) {    function() {        Console.log ("This 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 what 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 been 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 function (num) {     returnfunction() {           Console.log ("This is element #" +  num);      };};  for (var i = 0; i < n; i++) {    = Makehandler (i+1);}

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

Common ERROR 7: Prototype inheritance issues

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

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 New Baseobject (); var New Baseobject (' unique '); Console.log (firstobj.name);   // - Results in ' Default ' // Results in ' unique '

But what if we execute the DELETE statement:

Delete secondobj.name;

We will get:

//

But isn't it better to be able to go back to the ' default ' state? In fact, to achieve this effect is very simple, if we can use the prototype inheritance:

function (name) {    if(typeof name!== "undefined") {        this. Name= name;     = ' default ';

In this version, Baseobject inherits the name attribute from the prototype and is set to ' default '. At this point, if the constructor is called without parameters, it is automatically set to default. Similarly, if the Name property is moved from Baseobject, the system will automatically look for the prototype chain and get the ' default ' value:

var New Baseobject (' unique '); Console.log (thirdobj.name);   // Results in ' unique ' Delete Thirdobj.name;console.log (thirdobj.name);   // - Results in ' Default '
Common Error 8: Guidelines for creating an error for an instance method

Let's take a look at the following code:

var function () {}  function() {     Console.log (this = = window?) "Window": "MYOBJ"); };   var New MyObject ();

Now for the sake of convenience, we create a new variable to guide the WhoAmI method, so we can directly use WhoAmI () instead of the 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 is:

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

No mistakes!

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

Obj.whoami ();  // outputs "MYOBJ" (as expected)WhoAmI ();      // outputs "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 its this is referring to window, not obj!

The correct encoding should be:

 var  MyObject = function   () {}myobject.prototype.whoami  = function   () {Console.log ( this  = = = window? "Window": "MYOBJ"  var  obj = new     MyObject (); OBJ.W  = Obj.whoami; //   obj.whoami ();  //  outputs "MYOBJ" (as expected)        OBJ.W (); //  Outputs" MYOBJ "(as expected)  
Common Error 9: Use a string as the first parameter of settimeout or SetInterval

First we declare that there is no grammatical error in using a string as the first parameter of these two functions. But this is actually a very inefficient approach. Because from a system point of view, when you use a string, it is passed into the constructor, and another function is called again. This slows down the progress of the program.

SetInterval ("LogTime ()"),setTimeout ("LogMessage ('" + Msgvalue + "')", 1000);

Another method is to pass the function directly in as a parameter:

SetInterval (LogTime, +);   SetTimeout (function() {          logmessage (msgvalue);       1000);
Common Error 10: Ignoring the role of "strict mode"

"Strict mode" is a stricter code-checking mechanism and will make your code more secure. Of course, not selecting this mode does not mean that it is a mistake, but using this pattern will ensure that your code is more accurate.

Below we summarize the advantages of several "strict mode":

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

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

    3. Cancels the default transform for this: In normal mode, the This keyword is directed to null or undefined to automatically convert to global. In strict mode, we have canceled this default mechanism.

    4. Prevent duplicate variable declarations and parameter declarations: Duplicate variable declarations 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 the function declaration will cause an error, such as (e.g., function foo (val1, Val2, Val1) {}),

    5. Make the eval () function more secure.

    6. When an invalid delete instruction is encountered after the error: Delete instruction can not be performed on the properties of the class, under normal circumstances this situation is silently ignored, and in the strict mode will be error.
Conclusion

Just as with other technical languages, the deeper you know about JavaScript, 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 functionality will help you improve the efficiency of programming, reduce the problem of becoming.

"Turn" 10 JavaScript easy to make a small mistake, you a few shots?

Related Article

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.