Talk about some difficult problems in JavaScript grammar (i.)

Source: Internet
Author: User
Tags define object definition empty variables string variable window

1) Intro

Not long ago I set up a technology group in a MM asked a question like this, she posted the code as follows:

var a = 1;
function hehe ()
{
Window.alert (a);
var a = 2;
Window.alert (a);
}
Hehe ();

The results of the execution are as follows:

First Alert:

Second alert:

This is a surprising result, why does the first pop-up box show undefined instead of 1? The principle of this confusion I describe as follows:

A variable in a page that is directly defined under the script label is a global variable that is a variable of the Window object, and according to the JavaScript scope chain principle, when a variable cannot find the definition of the variable under the current scope, The JavaScript engine then looks up through the scope chain until it is looked up in the global scope, as shown in the preceding code, although the value of the variable is redefined within the function, but the function used the variable before the internal definition, the variable is used in accordance with the principle of the scope chain in the function's internal variable definition, The JavaScript engine should find the variable definition in the global scope, but the fact is that the variable is undefined, what the hell is going on?

At that time many people in the group gave the answer to the question, I also gave my own answer, in fact, this problem a long time ago I did study, but just been asked I actually still have a jam period, in addition to the recent research Javascriptmvc writing, found himself reading code to new, The use of prototype, apply, and call is still a long time to savor, so I think it is necessary to do a bit more difficult to understand the JavaScript basic grammar of the problem to do a comb, in fact One of the great benefits of blogging is that the logic of the knowledge you write is more profound than the logical image you have repeatedly combed through your mind.

Let's start with the main content of this article, and I'll begin with basics.

2 JavaScript variables

In the Java language there is a classic word: in the Java World, everything is an object .

JavaScript has nothing to do with Java, but many friends who use JavaScript think that everything is an object in the JavaScript world.

In fact, the JavaScript language and the Java language variables are divided into two types: the basic data type and the reference type.

The base type refers to: Undefined, Null, Boolean, number, and string, whereas a reference type refers to multiple objects, so the JavaScript object refers to the reference type. In Java you can say that everything is an object, because the Java language has an object encapsulation for all the basic types, and this is the same in JavaScript, so it's not too much to mention in the JavaScript world.

But in actual development, if we are not very clear about the difference between the basic type and the reference type, we will come across a lot of questions that we can't understand, let's take a look at the following code:

var str = "Sharpxiajun";

Str.attr01 = "Hello World";

Console.log (str);/Run Result: Sharpxiajun

Console.log (STR.ATTR01);/Run Result: undefined

Running, we found that as the basic data type, we couldn't add attributes to the variable, and of course the method was not, for example, the following code:

str.ftn = function () {
Console.log ("str ftn");
}
STR.FTN ();

Run, the result is as shown in the following figure:

When we use reference types, the result is completely different from the above, please see the following code:

    var obj1 = new Object ();      Obj1.name = "obj1 name";      Console.log (obj1.name);/Run Result: obj1 name

The difference between a basic type and a reference type in JavaScript is similar to that of other languages, but it's a long old question, but in reality many people understand it, but it's hard to use it to understand the problem.

The basic variable in JavaScript is stored in the stack area (stack memory in memory), its storage structure as shown in the following figure:


JavaScript refers to the storage of variables is more complex than the basic type of storage, the reference type of storage requires the memory of the stack area and heap area (heap area is the memory of the heap memory) to complete together, as shown in the following figure:

In JavaScript, a variable's storage contains three parts:

Part One: The variable designator of the stack area;

Part Two: The value of the stack region variable;

Part Three: The objects stored in the heap area.

The different definitions of variables, these three parts will also change, let me enumerate some typical scenarios:

Scene One: The following code shows :

    var qqq;      Console.log (QQQ);/Run Result: undefined

The run result is undefined, the standard explanation of the above code is that the variable is named, but has not initialized, at this time in the memory of the variable storage only has the stack area variable identifier and the stack area of the variable value, of course, there is no heap area stored objects.

Scenario Two: The following code shows :

    var qqq;      Console.log (QQQ)/running result: undefined
     console.log (XXX);

Run, the result is as shown in the following figure:

You are prompted that the variable is undefined. It is illegal to use variables undefined in any language, as we see in JavaScript, but when we do JavaScript development, it is often said that variables are not defined and can be used, how do I not use them in my example? So let's look at the following code:

xxx = "outer xxx";
Console.log (XXX)//Run Result: outer XXX
function testftn () {
SSS = "Inner SSS";
Console.log (SSS)//Run Result: outer SSS
}

TESTFTN ();
Console.log (SSS)//Run Result: outer SSS
Console.log (WINDOW.SSS)//Run Result: outer SSS

Defining variables in JavaScript requires the use of the Var keyword, but javascript can define variables without using Var, and in JavaScript we can directly assign values to variables that are not defined by Var, but at this point you are manipulating variables, Regardless of whether the operation is in the global scope or in the local scope, the variable ultimately belongs to the Window object, and we look at the structure of the Window object, as shown in the following illustration:

by these two scenes we can know in JavaScript the variable in the normal use of is reported "XXX is not defined "Error (under this error, followed by JavaScript code will not run correctly) only if this variable is not being var the definition also does not have an assignment operation to occur, and only the variable of the assignment operation, regardless of what the variable is assigned in that scope, is ultimately the global variable that is the window Object .

From the above I listed two scenes to understand the introduction of the user raised the question, the following I modify the code, as follows:

var a = 1;
function hehe ()
{
Console.log (a);
var a = 2;
Console.log (a);
}
Hehe ();

The results are shown in the following illustration:

I'll change the code again:

var a = 1;
function hehe ()
{
Console.log (a);
var a = 2;
Console.log (a);
}
Hehe ();

Run, the results are as follows:

In contrast to both the code and the code in the primer, we found that the key to the problem was the Var a=2. In code one I annotate the definition of a global variable, the result is consistent with the result of the code in the primer, which means that the use of a variable within the function is independent of the global environment, and I annotate the key code in the code two, var a = 2, the result of the code running changes, the program error, it is really confusing, The puzzle is that the location of the variable definition in the local scope is after the first time the variable is used, but the program does not complain, which does not conform to the principle that the JavaScript variable does not define the error.

In fact, this variable is still defined, that is, there are identifiers in the memory store, just not assigned, the code one shows that the internal variable A has nothing to do with the external environment, what's going on? This code cannot be understood if we understand the logic that runs according to the code and executes sequentially.

In fact, the variables in JavaScript and other languages are very different, javascript variable is a loose type, the loose type variable is characterized by the variable definition does not need to specify the type of variable, variable in the runtime can randomly change the type of data, However, this feature does not mean that JavaScript variables have no type, and that the JavaScript variables are typed when the variable type is determined. But in reality, many programmers think of JavaScript loosely typed as JavaScript variables that can be arbitrarily defined, that is, you can use the var definition, or the VAR definition, but in the JavaScript language the variable definition does not use VAR, and the variable must have an assignment operation , only the variable of the assignment operation is given to window, which is actually a way for JavaScript language designers to promote JavaScript security.

In addition to the loose type of JavaScript language and the characteristics of changing variable types at any time, many programmers think JavaScript variables are defined at run time, and some people think that JavaScript code has only a runtime, which is wrong. The JavaScript code has one more procedure before it is run: preload, the purpose of preloading is to construct the runtime environment such as the global environment, the function environment, the scope chain (on the scope chain and environment, this article will do a detailed explanation), and the environment and scope of the construction of the core content is Specify which category the good variable belongs to, so in the JavaScript language the definition of the variable is in preload completion rather than at run time.

So, the code in the primer is redefined in the local scope of the function, and the scope of a is framed at preload time, the A variable is no longer a global variable, but a function scope, except that the assignment The operation is performed at runtime (which is why the JavaScript language changes the type of the variable at runtime because the assignment is performed at run time), so the first time a variable is used, the A variable is not assigned in the local scope, only the name of the stack area. So the result is undefined.

However, the assignment operation is not completely unaffected by preload, the JavaScript engine scans all the code while preloading, but does not run it, and when the preload scans to the assignment, but the variable of the assignment operation is defined by VAR, the variable is given the global variable, the Window object.

Based on the above, we can also understand the JavaScript two special types: undefined and null, from the JavaScript variable storage in the three-part perspective, when the value of the variable is undefined, then the variable only the stack area of the indicator, If we assign operations to undefined variables, if the value is a basic type, then the value of the stack area is a value, if the stack area is an object then the heap area will have an object, and the value of the stack area is the address of the heap area object, if the variable value is NULL, we naturally think that the variable is an object, And it's an empty object, based on three parts of the variable storage I talked about earlier: when the variable is null, the stack area identifier and value will have a value, the heap area should also have, but the heap area is a null object, so that null is actually more memory than undefined, then we look at the following code:






Console.log (ooo = = null);/Run Result: true

Run, the result is very shocking Ah, null incredibly can and undefined equal, but use more accurate three equal sign "= =", found that the two are still a little different, in fact, JavaScript undefined type originated from null or null is undefined's parent class , essentially null and undefined except the name of this vest is different, the other is the same, but to make a variable is null must use equal sign "=" to be assigned.

When the variable is undefined and null when we abuse it the JavaScript language may be an error, the subsequent code will not work properly, so the JavaScript development specification requires variable definition when the best immediately assigned value, the value of the benefit is that we do not use the variable, It is very difficult for the program to terminate the program because the variable is not defined and the error for example, even if the variable is a string base type, in the Variable definition property program is still not an error, this is an important way to enhance the robustness of the program, by the example of the introduction we also know that the variable definition is best placed in the scope of the variable described the most front-end , doing so is an important means of ensuring code robustness.

Let's look at a piece of code here:

var str;

if (undefined!= str && null!= str && ""!= str) {
Console.log ("true");
}else{
Console.log ("false");
}

if (undefined!= str && ""!= str) {
Console.log ("true");
}else{
Console.log ("false");
}

if (null!= str && ""!= str) {
Console.log ("true");
}else{
Console.log ("false");
}

if (!! STR) {
Console.log ("true");
}else{
Console.log ("false");
}
str = "";
if (!! STR) {
Console.log ("true");
}else{
Console.log ("false");
}

Run, the results are all printed out false.

Using the double equal sign "=", undefined and null are one thing, so the first if statement is completely redundant, adding a lot of code, and the second and the third is equivalent, the essence of the first three kinds of writing is consistent, but in reality many programmers will choose to form one, The reason is that they have not yet understood the difference between undefined and null, and the fourth is a more perfect way of writing, in JavaScript if the condition of the IF statement is undefined and null, then the result of if is false, use! operator if evaluates to True, plus one is false, so here I recommend that when writing JavaScript code it is best to judge whether the code is undefined or null! Operator.

In code four, we see that when the string is assigned, but the assignment is an empty string, the condition of the If is also five basic types in false,javascript, undefined, null, Boolean, number, and string. Now we find that we can use it except number! To determine if ture and false, what is the base type number?


var num = 0;
if (!! NUM) {
Console.log ("true");
}else{
Console.log ("false");
}


Run, the result is false.

If we change num to a negative or positive number, then the result of the run is true.

This illustrates the point that when we define a variable initialization value, if the base type is string, we assign an empty string, and if the base type is number we assign a value of 0, then we can use the IF statement to determine if the variable is being used.

But when the variable is the object, the result is different, the following code:


var obj = {};
if (!! obj) {
Console.log ("true");
}else{
Console.log ("false");
}



Run, the code is true.

So when we define an object variable, we assign NULL to the variable when we initialize it so that the IF statement can determine whether the variable has been initialized.

Actually if Plus! Operation to judge the phenomenon of the object and mystery, this mystery to wait for me to finish three of the scene can be said clearly OH.

Scene Three: Copy the values of variables and function pass parameters

First look at the code for this scenario:


var S1 = "Sharpxiajun";
var s2 = S1;
Console.log (S1);////Run Result: Sharpxiajun
Console.log (S2);////Run Result: Sharpxiajun
S2 = "XTQ";
Console.log (S1);////Run Result: Sharpxiajun
Console.log (S2);////Run Result: XTQ



Above is the assignment of the base type variable, let's look at the following code:


var obj1 = new Object ();
Obj1.name = "obj1 name";
Console.log (obj1.name);/Run Result: obj1 name
var obj2 = obj1;
Console.log (obj2.name);/Run Result: obj1 name
Obj1.name = "Sharpxiajun";
Console.log (obj2.name);/Run Result: Sharpxiajun




We found that when the object was replicated, the Obj1 and Obj2 two objects were concatenated, and the properties of the OBJ1 variable were changed, and the OBJ2 attributes were modified.

The essence of the function pass argument is that the external variable is copied into the variable of the function parameter, and we look at the following code:


function testftn (snm,pobj) {
Console.log (sNm);/Run Result: New Name
Console.log (pobj.oname);/Run Result: New obj
sNm = "Change Name";
Pobj.oname = "Change obj";
}

var sNm = "New Name";
var pobj = {oname: "New obj"};
TESTFTN (Snm,pobj);
Console.log (sNm);/Run Result: New Name
Console.log (pobj.oname);/Run Result: Change obj

This result is consistent with the result of the variable assignment.

in JavaScript The pass parameter is passed by value .

The above function of the problem is a lot of companies love the interview question, in fact, many people do not know the nature of JavaScript reference, if the above cited examples to change the complex point, many friends will be down to this interview.

To illustrate the principle of this problem, we have to use the variable storage principle mentioned above, and here I repeat the contents of the preceding text again, two graphs, as follows:

This is the memory structure of the base type storage.

This is the memory structure of the reference type store.

There is also a knowledge, as follows:

In JavaScript, a variable's storage contains three parts:

Part One: The variable designator of the stack area;

Part Two: The value of the stack region variable;

Part Three: The objects stored in the heap area.

In JavaScript, the copy of a variable (the function argument is also a variable assignment) is essentially a transfer value, this value is the value of the stack area, and the base type is stored in the value of the stack, so after copying the base variable, the two variables are independent of each other, but when the reference type is copied, Copy operation or copy the value of the stack area, but this time the value is the address of the heap area object because the JavaScript language is not allowed to manipulate heap memory, so the variables for the heap memory are not replicated, so the value copied by the replication Reference object is the address of the heap memory, and the two variables used by the copy are the same. As a result, one of the copied variables modifies the object, and the other variable is affected.

The principle is finished, below I enumerate a overstating example, the code is as follows:

var ftn1 = function () {
Console.log ("test:ftn1");
};

var ftn2 = function () {
Console.log ("test:ftn2");
};

function ftn (f) {
f ();
f = ftn2;
}

FTN (FTN1);/Run Result: test:ftn1
Console.log ("==================== Gorgeous split line ======================");
FTN1 ()//Run Result: test:ftn1

This code was an early friend of mine to test me, I was correct, but I was a monk, ask my friend wrong answer, in fact, at that time we did not understand two of the reasons, my friend is so analyzed he thought F is a function of the parameters, belong to the function of the local scope, so change the value of F, is not able to change the value of FTN1, Because the external scope F is invalid, but this explanation is very difficult to explain the function I gave in the example of the argument, in fact, the answer is the function of the principle of argument, but here added a confusing factor function, in the JavaScript function is also the object, the local scope f = The ftn2 operation is to change the address of the F in the stack area to the FTN2 address, without any changes to the external ftn1 and FTN2.

Remember: JavaScript both the variable copy and the function reference are the values that are being passed in the stack area .

The value of the stack function in addition to the variable copy, it will also play a role in the IF statement, when the value of the stack area is undefined, null, "" (empty string), 0, False, if the condition of the judgment is false, we can pass! operator, so when our code is as follows:

var obj = {};
if (!! obj) {
Console.log ("true");
}else{
Console.log ("false");
}

The result is true, because var obj = {} is equivalent to var obj = new Object (), although there is nothing in the object, but in the heap area, the object's memory has been allocated, and the value of the variable stack is already the memory address, so the IF statement is true.

It seems that this topic can not be finished, in fact, I wrote this article is to say New,prototype,call (apply) and this, did not want to talk about the definition of variable said so much, forget, first published it, eat dinner and then write, hope to finish today.



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.