`
Odysseus_110
  • 浏览: 121033 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

javascript 权威指南 学习笔记1

阅读更多

 

If you attempt to read the value of an undeclared variable, JavaScript will generate an 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 must always use the var statement within function bodies. It's best to use var for all variables, whether global or local. (The distinction between local and global variables is explored in more detail in the next section.)

 

 

Within the body of a function, a local variable takes precedence over a global variable with the same name. If you declare a local variable or function parameter with the same name as a global variable, you effectively hide the global variable. For example, the following code prints the word "local":

 

var scope = "global";         // Declare a global variable

function checkscope(  ) {

    var scope = "local";      // Declare a local variable with the same name

    document.write(scope);    // Use the local variable, not the global one

}

checkscope(  );               // Prints "local" 
 

 

Although you 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 if you don't:

 

scope = "global";               // Declare a global variable, even without var

function checkscope(  ) {

    scope = "local";            // Oops! We just changed the global variable

    document.write(scope);      // Uses the global variable

    myscope = "local";          // This implicitly declares a new global variable

    document.write(myscope);    // Uses the new global variable

}

checkscope(  );                 // Prints "locallocal"

document.write(scope);          // This prints "local"

document.write(myscope);        // This prints "local" 
 

In general, functions do not know what variables are defined in the global scope or what they are being used for. Thus, if a function uses a global variable instead of a local one, it 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 var .

In JavaScript 1.2 (and ECMAScript v3), function definitions can be nested. Each function has its own local scope, so it is possible to have several nested layers of local scope. For example:

 

var scope = "global scope";          // A global variable

function checkscope(  ) {

    var scope = "local scope";       // A local variable

    function nested(  ) {

        var scope = "nested scope";  // A nested scope of local variables

        document.write(scope);       // Prints "nested scope"

    }

    nested(  );

}

checkscope(  ); 
 

Note that unlike C, C++, and Java, JavaScript does not have block-level scope. All variables declared in a function, no matter where they are declared, are defined throughout the function. In the following code, the variables i , j , and k all have the same scope: all three are defined throughout the body of the function. This would not be the case if the code were written in C, C++, or Java:

 

function test(o) {

    var i = 0;                         // i is defined throughout function

    if (typeof o == "object") {

        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 10

    }

    document.write(j);                 // j is defined, but may not be initialized

} 
 

The rule that all variables declared in a function are defined throughout the function can cause surprising results. The following code illustrates this:

 

var scope = "global";

function f(  ) {

    alert(scope);         // Displays "undefined", not "global"

    var scope = "local";  // Variable initialized here, but defined everywhere

    alert(scope);         // Displays "local"

}

f(  ); 
 

You might think that the first call to alert( ) would display "global", since the var statement declaring the local variable has not yet been executed. Because of the scope 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:

 

function f(  ) {

    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 it has a value

} 
 

This example illustrates why it is good programming practice to place all of your variable 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 JavaScript programming: there are two different kinds of undefined variables. The first kind of 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 undeclared variable does not cause an error; instead, it implicitly declares the variable in the global scope.

The second kind of undefined 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 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.

The following code fragment illustrates some of the differences between truly undefined 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. 

 

 

The next topic we need to consider is the content of variables. We often say that variables 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. The types can be divided into two groups: primitive types and reference types. Numbers, boolean values, and the null and undefined types are primitive. Objects, arrays, and functions are reference types.

A primitive type has a fixed size in memory. For example, a number occupies eight bytes of memory, and a boolean value can be represented with only one bit. The number type is 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] 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 length -- they do not have a fixed size. The same is true of arrays: an array can have any number of elements. Similarly, a function can contain any amount of JavaScript code. Since these types 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 value. Typically, this reference is some form of pointer or memory address. It is not the 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 primitive type):

 

 

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 the 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, that is being assigned in this statement. After that second line of code, we still have only one array object; we just happen to have two references to it.

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 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 a reference type.

 

 

 

Instead of requiring manual deallocation, JavaScript relies on a technique called garbage collection . The JavaScript interpreter is able to detect when an object will never again be used by the program. When it determines that an 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 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.

 

This means String is still reference type,but it's immutable .

4.6 Variables as Properties

You may have noticed by now that there are a lot of similarities in JavaScript between variables and the properties of objects. They are both assigned the same way, they are used the same way in JavaScript expressions, and so on. Is there really any fundamental 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 the JavaScript interpreter starts up, one of the first things it does, before executing any JavaScript code, is create a global object . The properties of this object are the global variables of JavaScript programs. When you declare a global JavaScript variable, what 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 part of a function), you can use the JavaScript keyword this to refer to the global object. Within functions, this has a different use, which is described in Chapter 7 .

In client-side JavaScript, the Window object serves as the global object for all JavaScript code contained in the browser window it represents. This global Window object has a self-referential 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 .

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 the value of global variables with the same name.

4.6.3 JavaScript Execution Contexts

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 call 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, in 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 one frame might refer to another frame with the expression 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 next section.

You don't need to fully understand how separate window and frame execution contexts 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.

 

 

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 of a special call object, we can return to the notion of variable scope and reconceptualize it. This new description of scope offers a useful way to think about variables in many contexts; it provides a powerful new understanding of how JavaScript works.

Every 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 x (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 object 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 moves on to the next object, and so on.

In top-level JavaScript code (i.e., code not contained within any function definitions), the scope chain consists of a single object, the global object. All variables are looked up in this 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 object, 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 checked second. A nested function would have three or more objects in its scope chain. Figure 4-1 illustrates the process of looking up a variable name in the scope chain of a function.

 


 

分享到:
评论

相关推荐

    Javascript权威指南学习笔记二

    ### JavaScript权威指南学习笔记二:客户端JavaScript #### 第十二章:Web浏览器中的JavaScript ##### 一、Web浏览器环境 在客户端JavaScript中,浏览器提供了一个特定的执行环境,其中`window`对象扮演着至关...

    Javascript权威指南学习笔记一

    JavaScript权威指南的学习笔记为我们深入理解这门语言的基础和特性提供了宝贵的资源。在第一部分中,主要探讨了JavaScript的核心概念和基本语法。 首先,JavaScript有两个主要的解释器:C语言编写的SpiderMonkey和...

    javascript权威指南笔记

    这份笔记包含了作者在研读《JavaScript权威指南》过程中的学习体会和理解,旨在帮助读者更有效地掌握JavaScript的核心概念、语法特性和实际应用技巧。 首先,JavaScript是一种广泛应用于网页和互联网应用的脚本语言...

    javascript权威指南 学习笔记之javascript数据类型

    [removed] /** JavaScript中允许使用 三种基本数据类型----数字,文本字符和布尔值。其中数字包括符点数. 此外,它还支持两种小数据类型---null(空)和undefined(未定义),该两种小数据类型,它们各自只定义...

    javascript参考教程javascript高级教程javascript权威指南(第四版)

    《JavaScript权威指南(第四版)》则是一本详尽的JavaScript学习资料,它涵盖了语言的最新发展,例如ES6及后续版本引入的新特性。这里你可以了解到箭头函数、解构赋值、类与继承、模板字符串、迭代器和生成器等。...

    Javascript权威指南笔记.docx

    《JavaScript权威指南》是一本深入探讨此语言的经典著作。以下是根据文档部分内容提炼的关键知识点: 1. **标识符**:在JavaScript中,标识符用来命名变量、函数等,必须以字母、下划线(_)或美元符号($)开头,...

    JavaScript基础知识总结.xmind

    通过思维导图的方式,快速了解掌握JavaScript的基本内容

    javascript权威指南 学习笔记之变量作用域分享

    在《JavaScript权威指南》第五版中,对变量作用域进行了深入的介绍,通过对作者的学习笔记梳理,我们可以系统地了解变量作用域相关的知识点。 首先,我们需要明确变量作用域的两个基本类型:全局作用域和局部作用域...

    javascript权威指南 学习笔记之null和undefined

    代码如下: &lt;!... &lt;... [removed] /** ******************null关键字******************** JavaScript中的关键字null是一个特殊的值,它表示“无值”。null常常被看作对象类型的一个特殊值,即代

    《jQuery权威指南》学习笔记之第1章 jQuery开发入门

    在实际学习过程中,通过阅读《jQuery权威指南》第1章并配合测试代码(未提供具体内容),可以更深入地理解和实践上述知识点,逐步掌握jQuery的开发基础。同时,不断练习和应用这些知识,才能真正提升开发技能,实现...

    《jQuery权威指南》学习笔记之第3章 jQuery操作DOM

    现在我们专注于《jQuery权威指南》第三章——jQuery操作DOM的内容。DOM,即文档对象模型,是HTML和XML文档的编程接口,它将文档结构转换为一个树形结构,方便程序进行读取和修改。jQuery提供了丰富的API,让开发者...

    JS权威指南(第四版)学习笔记.doc

    1. **脚本语言**:JavaScript使用简单的代码段进行编程,解释器在运行时逐行解释执行,降低了编程的复杂性。 2. **基于对象**:JavaScript允许使用和创建对象,其面向对象特性表现在可以通过对象的方法和属性来实现...

    《HTML5权威指南》笔记第一部分

    HTML5权威指南》笔记第一部分中提到的知识点涵盖了HTML5的基础概念、HTML页面结构、基本元素、浏览器兼容性、编辑器推荐以及HTML5中的一些新特性。以下是对这些知识点的详细介绍: ### HTML5基础概念 HTML5是第五代...

    《HTML5权威指南》笔记第四部分

    ### 《HTML5权威指南》笔记第四部分:深入理解DOM #### DOM概念解析 文档对象模型(Document Object Model,简称DOM)是HTML5的核心组成部分之一,它为网页开发者提供了一种将HTML文档转换成可编程对象的方式。通过...

    JavaScript 权威指南(第四版) 读书笔记

    在学习JavaScript的过程中,《JavaScript权威指南(第四版)》是一本非常经典的参考书,它详细介绍了JavaScript的语法、对象、函数以及一些高级特性。下面将根据提供的读书笔记内容,详细阐述一些重要的知识点。 ...

    《jQuery权威指南》学习笔记之第4章 jQuery中的事件与应用

    在深入探讨jQuery中的事件与应用之前,我们先要理解jQuery库的基本概念。...在阅读《jQuery权威指南》的第4章时,重点关注上述内容,结合实际项目进行实践,将有助于巩固和深化对jQuery事件处理的理解。

Global site tag (gtag.js) - Google Analytics