JavaScript variables, scopes, and memory issues (i)

Source: Internet
Author: User

The content of the next blog
    • Understanding the values of basic types and reference types
    • Understanding the execution Environment
    • Understanding Garbage Collection

As defined by ECMA-262, JavaScript variables differ greatly from those of other languages. The nature of the loosely typed JavaScript variable determines just one name that is used to hold a particular value at a specific time. Because there is no rule that defines what data type values A variable must hold, the value of the variable and its data type can change over the lifetime of the script. Although this may be an interesting, powerful, and problematic feature in some way, the actual complexity of JavaScript variables is much more than that.

values for base types and reference types

The ECMAScript variable may contain values for two different data types: the base type value and the reference type value. A primitive type value refers to a simple data segment, whereas a reference type value refers to an object that may consist of multiple values.

When assigning a value to a variable, the parser must determine whether the value is a base type value or a reference type value. The previous blog has discussed 5 basic data types: Undefined, Null, Boolean, number, and String. These 5 basic data types are accessed by value because you can manipulate the actual values that are saved in the variable.

The value of a reference type is an object that is saved in memory. Unlike other languages, JavaScript does not allow direct access to in-memory locations, which means that the object's memory space cannot be manipulated directly. When you manipulate an object, you are actually manipulating the object's reference rather than the actual object. To do this, the value of the reference type is accessed by reference.

提示:在很多语言中,字符串以对象的形式来表示,因此被认为是引用类型的。ECMAScript 放弃了这一传统。
Dynamic Properties

You define a primitive type value and a reference type value in a similar way: Create a variable and assign a value to the variable. However, when this value is saved to a variable, the actions that can be performed on the different types of values are quite distinct. For values of reference types, we can add properties and methods to them, and you can change and delete their properties and methods. Take a look at the following example:

varnewObject"Nicholas"//"Nicholas"

The above code creates an object and saves it in the variable person. We then added a property named name to the object and assigned the string value "Nicholas" to this property. The new property is then accessed through the alert () function. This property will persist if the object is not destroyed or if the property is not deleted.

However, we cannot add properties to the values of the base type, although doing so does not result in any errors. Like what:

var"Nicholas"27//undefined

In this example, we define a property named age for the string name and assign a value of 27 to the property. However, when this property is accessed on the next line, the attribute is found to be missing. This means that you can add properties dynamically to reference type values for future use.

Copy variable values

In addition to the way it is saved, there is a difference between copying the base type value and the reference type value from one variable to another. If you copy the value of the base type from one variable to another, a new value is created on the variable object, and the value is copied to the location assigned to the new variable. Take a look at an example:

var5;var num2 = num1;

In this case, the value saved in NUM1 is 5. When NUM2 is initialized with the value of NUM1, the value 5 is also saved in num2. However, 5 in num2 and 5 in NUM1 are completely independent, and this value is just a copy of 5 in NUM1. Thereafter, these two variables can participate in any operation without affecting each other. Visually demonstrates the process of copying a base type value.

When a value of a reference type is copied from one variable to another, the value stored in the variable object is also copied into the space allocated for the new variable. The difference is that a copy of this value is actually a pointer to an object stored in the heap. When the copy operation is finished, two variables will actually refer to the same object. Therefore, changing one of the variables will affect the other, as shown in the following example:

varnewObject();var"Nicholas"//"Nicholas"

First, the variable obj1 holds a new instance of the object. The value is then copied to the Obj2; in other words, both obj1 and Obj2 point to the same object. This way, when the Name property is added for Obj1, this property can be accessed through obj2 because both variables refer to the same object. This relationship is shown between the variables stored in the variable object and the objects held in the heap.

Passing Parameters

The parameters of all functions in ECMAScript are passed by value. In other words, copying the values from the outside of the function to the parameters inside the function is the same as copying the value from one variable to another. The delivery of a primitive type value is like a copy of a primitive type variable, whereas a reference to a value of a type is the same as a copy of a reference type variable.

Detection Type

To detect if a variable is a basic data type? The typeof operator described in the previous blog is the best tool. To be more specific, the TypeOf operator is the best tool for determining whether a variable is a string, a numeric value, a Boolean, or a undefined. If the value of the variable is an object or null, the TypeOf operator returns "Object" as shown in the following example:

/** * Description: Six big Data type tests. * Includes: * Five basic data types: Null,undefined,string,number,boolean * A large Complex type: Object */ var s =  "Nicholas" ; var  b = true ; var  i = 22 ; var  u; var  n = null ; var  o = new  Object (); alert (typeof s); //string  alert (typeof i); //number  alert (typeof B); //boolean  alert (typeof u); //undefined  alert (typeof N); //object  alert (typeof O); //object  

Although TypeOf is a very powerful helper when detecting a basic data type, this operator is of little use when detecting the value of a reference type. In general, we do not want to know that a value is an object, but rather to know what type of object it is. To do this, ECMAScript provides the instanceof operator, whose syntax is as follows:

resultconstructor

The instanceof operator returns true if the variable is an instance of the given reference type (identified by its prototype chain, and subsequent blogs will introduce the prototype chain). Take a look at the following example:

instanceofObject);  // 变量 person 是 Object 吗?instanceofArray// 变量 colors 是 Array 吗?instanceofRegExp// 变量 pattern 是 RegExp 吗

As a rule, all reference types have values that are instances of Object. Therefore, the instanceof operator always returns True when a reference type value and an Object constructor are instrumented. Of course, if you use the instanceof operator to detect a value of a base type, the operator always returns false because the base type is not an object.

"function"57"function" 。ECMA-262[[Call]]"function""function""object" 。
execution Environment and scope

The execution environment (execution context, which is sometimes referred to as "environment" for simplicity) is one of the most important concepts in JavaScript. The execution environment defines the other data that a variable or function has access to, and determines their respective behavior. Each execution environment has a variable object associated with it (variable object), and all variables and functions defined in the environment are stored in the object. Although the code we write does not have access to this object, the parser uses it in the background when it processes the data.

The global execution environment is one of the outermost execution environments. Depending on the hosting environment where the ECMAScript implementation resides, the objects that represent the execution environment are different. in a Web browser, the global execution environment is considered a window object (subsequent blogs will be discussed in detail), so all global variables and functions are created as properties and methods of the Window object. after all code in an execution environment is executed, the environment is destroyed, and all variables and function definitions stored therein are destroyed (the global execution environment is not destroyed until the application exits-for example, when the Web page or browser is closed).

Each function has its own execution environment. When the execution flow enters a function, the environment of the function is pushed into an environment stack. after the function executes, the stack pops up its environment and returns control to the previous execution environment. The execution flow in the **ecmascript program is controlled by this convenient mechanism.

When code executes in an environment, a scope chain of variable objects is created (scope chain). The purpose of a scope chain is to ensure an orderly access to all variables and functions that the execution environment has access to. The front end of the scope chain, which is always the variable object for the environment in which the code is currently executing. If the environment is a function, its active object (activation object) is used as the variable object. the active object initially contains only one variable (which can of course contain multiple variables, such as formal parameters, variables defined inside the function), i.e. the arguments object (which is not present in the global environment). The next variable object in the scope chain comes from the containing (external) environment, and the next variable object comes from the next containment environment. In this way, it continues to the global execution environment; The variable object of the global execution environment is always the last object in the scope chain. (That is, in the scope chain, each execution environment corresponds to a variable object.) Variable objects can contain multiple variables. )

Identifier parsing is the process of searching identifiers one level at a scope chain. The search process always starts at the front end of the scope chain, and then goes backward backwards until the identifier is found (if an identifier is not found, this usually results in an error). Take a look at the following sample code:

color"blue";function changeColor(){    if (color"blue"){        color"red";    else {        color"blue";    }}changeColor();alert("Color is now "color);

In this simple example, the scope chain of the function ChangeColor () contains two objects: its own variable object (which defines the arguments object) and the variable object of the global environment. The variable color can be accessed inside the function, because it can be found in this scope chain.

In addition, variables defined in a local scope can be used interchangeably with global variables in a local context, as shown in the following example:

var  color =  "blue" ; function  changeColor   ()  { var  anothercolor =  "red" ; function  swapColors           ()  { var  tempcolor = Anothercolor;        Anothercolor = color;        color = Tempcolor;    //here you can access color, Anothercolor, and Tempcolor } //here you can access color and anothercolor, but you cannot access Tempcolor  swapcolors ();} //can only access color  changecolor ();  

The above code involves a total of 3 execution environments: The global environment, the local environment of the ChangeColor (), and the local environment of the swapcolors (). There is a variable color and a function changecolor () in the global environment. The local Environment of ChangeColor () has a variable named Anothercolor and a function named Swapcolors (), but it can also access the variable color in the global environment. The local Environment of Swapcolors () has a variable tempcolor, which can only be accessed in this environment. Local environments, whether global or ChangeColor (), do not have access to tempcolor. However, within swapcolors (), you can access all the variables in the other two environments, because those two environments are its parent execution environment. Visually shows the scope chain of the previous example.

The rectangle in represents a specific execution environment. The internal environment can access all external environments through the scope chain, but the external environment cannot access any variables and functions in the internal environment. The linkages between these environments are linear and sequential. Each environment can search up the scope chain to query for variables and function names, but any environment cannot enter another execution environment by searching down the scope chain. For Swapcolors () in this example, its scope chain contains 3 objects: A Variable object of swapcolors (), a variable object of ChangeColor (), and a global variable object. The local Environment of Swapcolors () begins by searching for variables and function names in its own variable object, and then searches for the upper-level scope chain if the search is not found. The scope chain of ChangeColor () contains only two objects: its own variable object and the global variable object. This means that it does not have access to the swapcolors () environment.

提示:函数参数也被当作变量来对待,因此其访问规则与执行环境中的其他变量相同。
extend the scope chain

Although there are only two types of execution environments-Global and local (functions)-There are other ways to extend the scope chain. This is because some statements can temporarily add a variable object to the front end of the scope chain, and the variable object is removed after the code executes. This behavior can occur in both cases. Specifically, the scope chain is extended when the execution stream enters any of the following statements:

    • The catch block of the Try-catch statement;
    • With statement.

Both statements add a variable object to the front of the scope chain. For the WITH statement, the specified object is added to the scope chain. For a catch statement, a new variable object is created that contains the declaration of the thrown error object. Let's look at an example below.

function buildUrl() {    var"?debug=true";    with(location){        var url = href + qs;    }    return url;}

Here, the WITH statement receives the location object, so its variable object contains all the properties and methods of the Location object, and the variable object is added to the front end of the scope chain. A variable QS is defined in the BuildUrl () function. When the variable href is referenced in the WITH statement (actually referencing location.href), it can be found in the variable object of the current execution environment. When referring to the variable QS, the variable that is defined in BuildUrl () is referenced in the variable object in the function environment. As for the inside of the WITH statement, a variable named URL is defined, so the URL becomes part of the function execution environment, so it can be returned as the value of the function.

IE8JavaScript 实现中,存在一个与标准不一致的地方,即在catchcatchcatch 块的外部也可以访问到错误对象。IE9 修复了这个问题。
no block-level scopes

JavaScript without block-level scopes often leads to confusion in understanding. In other class C languages, blocks of code that are enclosed by curly braces have their own scopes (in the case of ECMAScript, which is their own execution environment), and thus support the definition of variables based on conditions. For example, the following code does not get the imagined result in JavaScript:

if (true) {    var"blue"//"blue"

Here is the variable color defined in an if statement. If it is in C, C + +, or Java, color is destroyed after the IF statement has finished executing. In JavaScript, however, variable declarations in the IF statement add variables to the current execution environment (in this case, the global environment). This difference is especially important to keep in mind when using a for statement, such as:

for (var i=010; i++){    //10

For a block-scoped language, the variables defined by the expression of the for-statement initialization variable will only exist in the context of the loop. For JavaScript, the variable I created by the for statement will still exist in the execution environment outside the loop even after the for loop execution has ended.

declaring Variables

Variables declared with Var are automatically added to the closest environment. Within the function, the closest environment is the local environment of the function, and in the With statement, the closest environment is the function environment. If you initialize a variable without using the var declaration, the variable is automatically added to the global environment. As shown below:

function add(num1, num2) {    sum = num1 + num2;    returnsum;}var result = add(1020//30alert(sum//由于 sum 不是有效的变量,因此会导致错误

The function add () in the above code defines a local variable named sum that contains the result of the addition operation. Although the result value is returned from the function, the variable sum is not accessible outside the function. If you omit the var keyword from this example, when add () finishes executing, sum will also be accessible to:

function add(num1, num2) {    sum = num1 + num2;    returnsum;}var result = add(1020//30alert(sum//30

The variable sum in this example does not use the var keyword when the assignment is initialized. Then, when Add () is finished, the variable sum added to the global environment will continue to exist, even if the function has been executed, and the subsequent code can still access it.

提示:在编写 JavaScript 代码的过程中,不声明而直接初始化变量是一个常见的错误做法,因为这样可能会导致意外。我们建议在初始化变量之前,一定要先声明,这样就可以避免类似问题。在严格模式下,初始化未经声明的变量会导致错误。
Query Identifiers

When you reference an identifier in an environment for reading or writing, you must search to determine what the identifier actually represents. The search process starts at the front end of the scope chain and queries the identifiers that match the given name upwards. If the identifier is found in the local environment, the search process stops and the variable is ready. If the variable name is not found in the local environment, it continues to search up the scope chain. The search process goes back to the variable object of the global environment. If the identifier is not found in the global environment, it means that the variable is not yet declared.

With this example, you can understand the process of querying identifiers:

var"blue";function getColor(){    return//"blue"

Calling the function GetColor () in this example will refer to the variable color. To determine the value of a variable color, a two-step search process begins. First, search for a variable object of GetColor () to find out if it contains an identifier named color. In the case where it is not found, the search continues to the next variable object (the variable object of the global environment) and the identifier named color is found there. Because a variable object that defines the variable is searched, the search process is declared closed. Figure 4-4 shows the search process visually.

In this search process, if there is a local definition of the variable, the search stops automatically and no longer enters another variable object. In other words, if there is an identifier with the same name in the local environment, the identifier in the parent environment is not used, as shown in the following example:

var"blue";function getColor(){    var"red";    return//"red"

The modified code declares a local variable named color in the GetColor () function. When the function is called, the variable is declared. When the second line of code in the function executes, it means that the value of the variable color must be found and returned. The search process begins with a local environment, and a variable named color is found here with the value "red". Because the variable is already found, the search stops, the return statement uses the local variable, and the function returns "Red". That is, any code that follows the declaration of a local variable color cannot access the global color variable without using window.color .

Why is it possible to access through Window.color??

A: The global execution environment is one of the outermost execution environments. Depending on the hosting environment where the ECMAScript implementation resides, the objects that represent the execution environment are different. in a Web browser, the global execution environment is considered a window object (subsequent blogs will be discussed in detail), so all global variables and functions are created as properties and methods of the Window object. after all code in an execution environment is executed, the environment is destroyed, and all variables and function definitions stored therein are destroyed (the global execution environment is not destroyed until the application exits-for example, when the Web page or browser is closed).

提示:变量查询也不是没有代价的。很明显,访问局部变量要比访问全局变量更快,因为不用向上搜索作用域链。JavaScript 引擎在优化标识符查询方面做得不错,因此这个差别在将来恐怕就可以忽略不计了。
Summary:
  • When code executes in an environment, a scope chain of variable objects is created (scope chain). The purpose of a scope chain is to ensure an orderly access to all variables and functions that the execution environment has access to. The front end of the scope chain, which is always the variable object for the environment in which the code is currently executing. If the environment is a function, its active object (activation object) is used as the variable object. the active object initially contains only one variable (which can of course contain multiple variables, such as formal parameters, variables defined inside the function), i.e. the arguments object (which is not present in the global environment). The next variable object in the scope chain comes from the containing (external) environment, and the next variable object comes from the next containment environment. In this way, it continues to the global execution environment; The variable object of the global execution environment is always the last object in the scope chain. (That is, in the scope chain, each execution environment corresponds to a variable object.) Variable objects can contain multiple variables. )
  • The code that exists for the execution environment has functions and script tags (different script tags count as the same execution environment, the global environment), so if, for, switch ... And so on. All of the remaining statements have no execution environment, so the variables defined in them exist in the current execution environment, that is, the function execution environment or the global execution environment. The function execution environment can be nested (the multi-tier execution environment is superimposed by the function, while the global execution environment is always the outermost layer of the overlay execution environment). For Try-catch, with only extended scopes (properties and methods that introduce an object from the outside, called an extension scope), Try-catch, with, does not have an execution environment.
  • If the execution environment is nested in multiple layers in the function, then in the non-strict mode there is a way to declare the variable directly in the global environment, that is, declare the variable without the Var declaration, note that the Var declaration must be assigned value (initialization), otherwise it will error!!!
  • The global execution environment is one of the outermost execution environments. Depending on the hosting environment where the ECMAScript implementation resides, the objects that represent the execution environment are different. in a Web browser, the global execution environment is considered a window object (subsequent blogs will be discussed in detail), so all global variables and functions are created as properties and methods of the Window object. after all code in an execution environment is executed, the environment is destroyed, and all variables and function definitions stored therein are destroyed (the global execution environment is not destroyed until the application exits-for example, when the Web page or browser is closed). *
  • This will also be a good way to understand the location of the JavaScript declaration variables and the lookup order of the variables.

The declaration of the function also satisfies the execution environment:

    /**     * 创建两个show方法。     */    function show(){        alert(‘外部show‘);    }    function controler() {        function show() {            alert(‘内部show‘)        }        show();    }    /**     * 调用方法开始测试。     */    //内部show    //外部show

JavaScript variables, scopes, and memory issues (i)

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.