Variables

11 295 0
Variables

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

Chapter 4. Variables A variable is a name associated wit the value. Variables allow you to sto h a value; we say that the variable stores or contains re and manipulate data in your programs. For riable, sum: 3; ut e of example, the following line of JavaScript assigns the value 2 to a variable named i: i = 2; And the following line adds 3 to i and assigns the result to a new va var sum = i + These two lines of code demonstrate just about everything you need to know abo variables. However, to fully understand how variables work in JavaScript, you need to master a few more concepts. Unfortunately, these concepts require more than a coupl lines of code to explain! The rest of this chapter explains the typing, declaration, scope, contents, and resolution of variables. It also explores garbage collection and the variable/property duality. [1] [1] These are tricky concepts, and a complete understanding of this chapter requires an understanding of concepts introduced in later chapters of the book. If you are relatively new to programming, you may want to read only the first two sections of this chapter and then move on to Chapter 5, Chapter 6, and Chapter 7 before returning to finish up the remainder of this chapter. 4.1 Variable Typing An important difference between JavaScript and languages such as Java and C is that JavaScript is untyped. This means, in part, that a JavaScript variable can hold a value of hich can hold only the one particular type of is perfectly legal in JavaScript to assign a va, or any other strongly typed language, code like this is illegal. A feature related to JavaScript's lack of typing is that the language conveniently and f you attempt to append a number to a string, for example, JavaScript automatically converts the number ing string so that it can be appended. We'll see more about data type onversion in Chapter 11 any data type, unlike a Java or C variable, w data for which it is declared. For example, it number to a variable and then later assign a string to that variable: i = 10; i = "ten"; In C, C++, Ja automatically converts values from one type to another, as necessary. I to the correspond c . tage of strongly typed languages such as C++ and Java is that they enforce rigorous programming JavaScript is obviously a simpler language for being untyped. The advan practices, which makes it easier to write, maintain, and reuse long, complex programs. are shorter scripts, this rigor is not necessary and we enefit from the simpler syntax. Since many JavaScript programs b 4.2 Variable Declaration Before you use a variable in a JavaScript program, you must declare it. [2] Variable declared with the s are declare it implicitly for you. var i = 0, j = 0, k = 0; is var keyword, like this: [2] If you don't declare a variable explicitly, JavaScript will var i; var sum; You can also declare multiple variables with the same var keyword: var i, sum; And you can combine variable declaration with variable initialization: var message = "hello"; If you don't specify an initial value for a variable with the var statement, the variable declared, but its initial value is undefined until your code stores a value into it. Note that the var statement can also appear as part of the for and for/in loops (introduced in Chapter 6), allowing you to succinctly declare the loop variable as part the loop syntax itself. For example: of for(var i = 0; i < 10; i++) document.write(i, "<br>"); i++,j--) document.write(i*j, "<br>"); te(i, "<br>"); e for(var i = 0, j=10; i < 10; for(var i in o) document.wri Variables declared with var are permanent: attempting to delete them with the delet operator causes an error. (The delete operator is introduced in Chapter 5.) 4.2.1 Repeated and Omitted Declarations It is legal and harmless to declare a variable more than once with the var statement. If t repeated declaration has an initializer, it acts as if it were simply an assignment statement he . If you attempt to read the value of an undeclared variable, JavaScript will generate an best to use var for all ariables, whether global or local. (The distinction between local and global variables is ble Scope l defined everywhere in your JavaScript code. On the e nt riable e same r example, the ar scope = "global"; // Declare a global variable function checkscope( ) { checkscope( ); // Prints "local" ou can get away with not using the var statement when you write code in the global scope, you must always use var to declare local variables. Consider what happens le, even obal e(scope); // Uses the global variable cal"; // This implicitly declares a new (myscope); // Uses the new global variable checkscope( ); // Prints "locallocal" document.write(scope); // This prints "local" document.write(myscope); // This prints "local" error. If you assign a value to a variable that you have not declared with var, JavaScript will implicitly declare that variable for you. Note, however, that implicitly declared variables are always created as global variables, even if they are used within the body of a function. To prevent the creation of a global variable (or the use of an existing global variable) when you meant to create a local variable for use within a single function, you ust always use the var statement within function bodies. It'sm v explored in more detail in the next section.) 4.3 Varia The scope of a variable is the region of your program in which it is defined. A globa variable has global scope -- it is other hand, variables declared within a function are defined only within the body of th function. They are local variables and have local scope. Function parameters also cou as local variables and are defined only within the body of the function. Within the body of a function, a local variable takes precedence over a global va th the same name. If you declare a local variable or function parameter with thwi name as a global variable, you effectively hide the global variable. Fo following code prints the word "local": v var scope = "local"; // Declare a local variable with the same name document.write(scope); // Use the local variable, not the global one } Although y if you don't: scope = "global"; // Declare a global variab without var function checkscope( ) { scope = "local"; // Oops! We just changed the gl levariab document.writ myscope = "lo global variable document.write } In general, functions do not know what variables are defined in the global scope or w they are being used for. Thus, if a function uses a global variable instead of a loc runs the risk of changing a value upon which some other part of the program relies. Fortunately, avoiding this problem is simple: declare all variables with hat al one, it In JavaScript 1.2 (and ECMAScript v3), function definitions can be nested. Each function so it is possible to have several nested layers of local scope. For e"; // A nested scope of local ); lock-level scope. All ion, no matter where they are declared, are defined the following code, the variables i, j, and k all have the same e the = 0; // i is defined throughout if (typeof o == "object") { 10 / j is defined, but ay not be can rprising results. The following code illustrates this: var. has its own local scope, example: var scope = "global scope"; // A global variable function checkscope( ) { var scope = "local scope"; // A local variable function nested( ) { var scope = "nested scop variables document.write(scope); // Prints "nested scope" } nested( ); } ckscope(che 4.3.1 No Block Scope Note that unlike C, C++, and Java, JavaScript does not have b variables declared in a funct on. In throughout the functi scope: all three are defined throughout the body of the function. This would not b case if the code were written in C, C++, or Java: function test(o) { var i unctionf var j = 0; // j is defined everywhere, not just block for(var k = 0; k < 10; k++) { // k is defined everywhere, not just loop document.write(k); } document.write(k); // k is still defined: prints } document.write(j); / m initialized } The rule that all variables declared in a function are defined throughout the function cause su var scope = "global"; function f( ) { alert(scope); // Displays "undefined", not "global" var scope = "local"; // Variable initialized here, but defined everywhere You might think that the first call to alert( ) would display "global", since the var scope function f( ) { it has a value ood programming practice to place all of your variable ript st kind of ed ndefined variable is one that has been declared but has never had a value assigned to it. If you read the value of one of these variables, you obtain its default The following code fragment illustrates some of the differences between truly undefined alert(scope); // Displays "local" } f( ); statement declaring the local variable has not yet been executed. Because of the rules, however, this is not what happens. The local variable is defined throughout the body of the function, which means the global variable by the same name is hidden throughout the function. Although the local variable is defined throughout, it is not actually initialized until the var statement is executed. Thus, the function f in the previous example is equivalent to the following: var scope; // Local variable is declared at the start of the function alert(scope); // It exists here, but still has "undefined" value scope = "local"; // Now we initialize it and give it a value alert(scope); // And here } This example illustrates why it is g declarations together at the start of any function. 4.3.2 Undefined Versus Unassigned The examples in the previous section demonstrate a subtle point in JavaSc programming: there are two different kinds of undefined variables. The fir undefined variable is one that has never been declared. An attempt to read the value of such an undeclared variable causes a runtime error. Undeclared variables are undefined because they simply do not exist. As described earlier, assigning a value to an undeclar variable does not cause an error; instead, it implicitly declares the variable in the global scope. The second kind of u value, undefined. This type of undefined variable might more usefully be called unassigned, to distinguish it from the more serious kind of undefined variable that has not even been declared and does not exist. and merely unassigned variables: var x; // Declare an unassigned variable. Its value is undefined. alert(u); // Using an undeclared variable causes an error. u = 3; // Assigning a value to an undeclared variable creates the variable. 4.4 Primitive Types and Reference Types The next topic we need to consider is the content of variables. We often say that variables The types can be divided into two groups: primitive types and reference types. Numbers, boolean rrays, and functions are ight bytes f memory, and a boolean value can be represented with only one bit. The number type is have or contain values. But just what is it that they contain? To answer this seemingly simple question, we must look again at the data types supported by JavaScript. values, and the null and undefined types are primitive. Objects, a reference types. A o primitive type has a fixed size in memory. For example, a number occupies e the largest of the primitive types. If each JavaScript variable reserves eight bytes of memory, the variable can directly hold any primitive value. [3] [3] gth - r pes do not have a fixed size, their values cannot be stored directly in the eight bytes of memory associated with each variable. Instead, the variable stores a reference to the t the rimitive type): he This is an oversimplification and is not intended as a description of an actual JavaScript implementation. Reference types are another matter, however. Objects, for example, can be of any len - they do not have a fixed size. The same is true of arrays: an array can have any numbe of elements. Similarly, a function can contain any amount of JavaScript code. Since these ty value. Typically, this reference is some form of pointer or memory address. It is no data value itself, but it tells the variable where to look to find the value. The distinction between primitive and reference types is an important one, as they behave differently. Consider the following code that uses numbers (a p var a = 3.14; // Declare and initialize a variable var b = a; // Copy the variable's value to a new variable a = 4; // Modify the value of the original variable alert(b) // Displays 3.14; the copy has not changed There is nothing surprising about this code. Now consider what happens if we change t code slightly so that it uses arrays (a reference type) instead of numbers: var a = [1,2,3]; // Initialize a variable to refer to an array var b = a; // Copy that reference into a new variable a[0] = 99; // Modify the array using the original reference alert(b); // Display the changed array [99,2,3] using the new reference If this result does not seem surprising to you, you're already well familiar with the distinction between primitive and reference types. If it does seem surprising, take a closer look at the second line. Note that it is the reference to the array value, not the array itself, th on references to it. at is being assigned in this statement. After that second line of code, we still have only e array object; we just happen to have two If the primitive versus reference type distinction is new to you, just try to keep the variable contents in mind. Variables hold the actual values of primitive types, but they hold only references to the values of reference types. The differing behavior of primitive and reference types is explored in more detail in Section 11.2. You may have noticed that I did not specify whether strings are primitive or reference types in JavaScript. Strings are an unusual case. They have variable size, so obviously they cannot be stored directly in fixed-size variables. For efficiency, we would expect JavaScript to copy references to strings, not the actual contents of strings. On the other hand, strings behave like a primitive type in many ways. The question of whether strings are a primitive or reference type is actually moot, because strings are immutable: there is a reference type. s location, and the variables merely hold a reference to that location. Now we need to focus briefly on the actual storage of the value. string, array, or object, the interpreter must allocate memory to store that entity. or ue called garbage tect when an object will never again be object is unreachable (i.e., there is no longer any way to refer to it using the variables in the program), it knows that the object no way to change the contents of a string value. This means that we cannot construct an example like the previous one that demonstrates that arrays are copied by reference. In the end, it doesn't matter much whether you think of strings as an immutable reference type that behaves like a primitive type or as a primitive type implemented with the internal efficiency of 4.5 Garbage Collection Reference types do not have a fixed size; indeed, some of them can become quite large. As we've already discussed, variables do not directly hold reference values. The value i stored at some other Since strings, objects, and arrays do not have a fixed size, storage for them must be llocated dynamically, when the size is known. Every time a JavaScript program createsa a Whenever memory is dynamically allocated like this, it must eventually be freed up f reuse, or the JavaScript interpreter will use up all the available memory on the system and crash. In languages like C and C++, memory must be freed manually. It is the programmer's responsibility to keep track of all the objects that are created and to destroy them (freeing their memory) when they are no longer needed. This can be an onerous task and is often the source of bugs. Instead of requiring manual deallocation, JavaScript relies on a techniq collection. The JavaScript interpreter is able to de used by the program. When it determines that an is no longer needed and its memory can be reclaimed. Consider the following lines of code, for example: var s = "hello"; // Allocate memory for a string var u = s.toUpperCase( ); // Create a new string s = u; // Overwrite reference to original string After this code runs, the original string "hello" is no longer reachable -- there are no references to it in any variables in the program. The system detects this fact and frees up its storage space for reuse. Garbage collection is automatic and is invisible to the programmer. You can create all the garbage objects you want, and the system will clean up after you! You need to know only enough about garbage collection to trust that it works; you don't have to wonder about where all the old objects go. For those who aren't satisfied, however, Section 11.3, contains further details on the JavaScript garbage-collection process. 4.6 Variables as Properties n both assigned the same way, they are ally any fundamental the JavaScript interpreter starts up, one of the first things it does, before executing roperties of this object are the global e a global JavaScript variable, what part of a function), you can use the ject. Within functions, this has a You may have noticed by now that there are a lot of similarities in JavaScript betwee variables and the properties of objects. They are used the same way in JavaScript expressions, and so on. Is there re difference between the variable i and the property i of an object o? The answer is no. Variables in JavaScript are fundamentally the same as object properties. 4.6.1 The Global Object When any JavaScript code, is create a global object. The p variables of JavaScript programs. When you declar you are actually doing is defining a property of the global object. The JavaScript interpreter initializes the global object with a number of properties that refer to predefined values and functions. For example, the Infinity, parseInt, and Math properties refer to the number infinity, the predefined parseInt( ) function, and the predefined Math object. You can read about these global values in the core reference section of this book. In top-level code (i.e., JavaScript code that is not JavaScript keyword this to refer to the global ob different use, which is described in Chapter 7. In client-side JavaScript, the Window object serves as the global object for all JavaScr code contained in the browser window it represents. This global Window object has a self-referential ipt window property that can be used instead of this to refer to the global object. The Window object defines the core global properties, such as parseInt and Math, and also global client-side properties, such as navigator and screen. the 4.6.3 JavaScript Execution Contexts l 4.6.2 Local Variables: The Call Object If global variables are properties of the special global object, then what are local variables? They too are properties of an object. This object is known as the call object. The call object has a shorter life span than the global object, but it serves the same purpose. While the body of a function is executing, the function arguments and local variables are stored as properties of this call object. The use of an entirely separate object for local variables is what allows JavaScript to keep local variables from overwriting value of global variables with the same name. Each time the JavaScript interpreter begins to execute a function, it creates a new execution context for that function. An execution context is, obviously, the context in which any piece of JavaScript code executes. An important part of the context is the object in which variables are defined. Thus, JavaScript code that is not part of any function runs in an execution context that uses the global object for variable definitions. And every JavaScript function runs in its own unique execution context with its own cal object in which local variables are defined. An interesting point to note is that JavaScript implementations may allow multiple global execution contexts, each with a different global object. (Although, in this case, each global object is not entirely global.) [4] The obvious example is client-side JavaScript, i which each separate browser window, or each frame within a window, defines a separate global execution context. Client-side JavaScript code in each frame or window runs in its own execution context and has its own global object. However, these separate client-side global objects have properties that link them to one another. Thus, JavaScript code in frame might refer to another frame with the expression n one t section. me execution contexts parent.frames[1], and the global variable x in the first frame might be referenced by the expression parent.frames[0].x in the second frame. [4] This is merely an aside; if it does not interest you, feel free to move on to the nex You don't need to fully understand how separate window and fra are linked together in client-side JavaScript right now. We'll cover that topic in detail when we discuss the integration of JavaScript with web browsers in Chapter 12. What you should understand now is that JavaScript is flexible enough that a single JavaScript interpreter can run scripts in different global execution contexts and that those contexts need not be entirely separate -- they can refer back and forth to each other. This last point requires additional consideration. When JavaScript code in one execu context can read and write property values and execute functions that are defined in another e tion xecution context, we've reached a level of complexity that requires consideration of security issues. Take client-side JavaScript as an example. Suppose browser window A is running a script or contains information from your local intranet, and window B is running a script from some random site out on the Internet. In general, we do not want to allow the code in window B to be able to access the properties of window A. If we allow it to do this, it might be able to read sensitive company information and steal it, for example. Thus, in order to safely run JavaScript code, ther must be a security mechanism that preve e nts access from one execution context to another when such access should not be permitted. We'll return to this topic in Chapter 21. , of a special call object, we can return to the notion of variable scope and reconceptualize it. This new description of variables in m JavaScript works. very JavaScript execution context has a scope chain associated with it. This scope chain is a list or chain of objects. When JavaScript code needs to look up the value of a variable (a process called variable name resolution), it starts by looking at the first object in the chain. If that object has a property named x, the value of that property is used. If the first bject does not have a property named x, JavaScript continues the search with the next object in the chain. If the second object does not have a property named x, the search oves on to the next object, and so on. top-level JavaScript code (i.e., code not contained within any function definitions), the e global object. All variables are looked up in is object. If a variable does not exist, the variable value is undefined. In a (non-nested) function, however, the scope chain consists of two objects. The first is the function's call bject, and the second is the global object. When the function refers to a variable, the call object (the local scope) is checked first, and the global object (the global scope) is hecked second. A nested function would have three or more objects in its scope chain. Figure 4-1 4.7 Variable Scope Revisited When we first discussed the notion of variable scope, I based the definition solely on the lexical structure of JavaScript code: global variables have global scope and variables declared in functions have local scope. If one function definition is nested within another variables declared within that nested function have a nested local scope. Now that we know that global variables are properties of a global object and that local variables are properties scope offers a useful way to think about any contexts; it provides a powerful new understanding of how E x o m In scope chain consists of a single object, th th o c illustrates the process of looking up a variable name in the scope chain of a nction. Figure 4-1. The scope chain and variable resolution fu . Contexts l 4.6.2 Local Variables: The Call Object If global variables are properties of the special global object, then what are local variables? They too. code: global variables have global scope and variables declared in functions have local scope. If one function definition is nested within another variables

Ngày đăng: 05/10/2013, 13:20

Từ khóa liên quan

Tài liệu cùng người dùng

Tài liệu liên quan