重新复习js

43次阅读

共计 13021 个字符,预计需要花费 33 分钟才能阅读完成。

复习 js day1

js 基础

JavaScript 到底是什么

JavaScript 的应用场合极其广泛。简单到幻灯片、照片库、浮动布局和响应按钮点击。复杂到游戏、2D 和 3D 动画、大型数据库驱动程序,等等。

JavaScript 相当简洁,却非常灵活。开发者们基于 JavaScript 核心编写了大量实用工具,可以使 开发工作事半功倍。其中包括:

  • 浏览器应用程序接口(API)—— 浏览器内置的 API 提供了丰富的功能,比如:动态创建 HTML 和设置 CSS 样式、从用户的摄像头采集处理视频流、生成 3D 图像与音频样本,等等。
  • 第三方 API —— 让开发者可以在自己的站点中整合其它内容提供者(Twitter、Facebook 等)提供的功能。
  • 第三方框架和库 —— 用来快速构建网站和应用。

变量

变量的定义和数据类型

在应用程序中,使用变量来作为值的符号名。变量的名字又叫做标识符,其需要遵守一定的规则。

一个 JavaScript 标识符必须以字母、下划线(_)或者美元符号($)开头;后续的字符也可以是数字(0-9)。因为 JavaScript 语言是区分大小写的,所以字母可以是从“A”到“Z”的大写字母和从“a”到“z”的小写字母。

变量 解释
string 字符串(一串文本)。字符串的值必须将用引号(单双均可,必须成对)扩起来。
Number 数字。无需引号。
Boolean 布尔值(真 / 假)。true/false 是 JS 里的特殊关键字,无需引号。
Array 数组,用于在单一引用中存储多个值的结构
Object 对象,JavaScript 里一切皆对象,一切皆可储存在变量里。这一点要牢记于心。

数据类型的转换

字符串转换为数字
有一些方法可以将内存中表示一个数字的字符串转换为对应的数字。parseInt()和 parseFloat()

parseInt 方法只能返回整数,所以使用它会丢失小数部分。另外,调用 parseInt 时最好总是带上进制(radix) 参数,这个参数用于指定使用哪一种进制。

将字符串转换为数字的另一种方法是使用一元加法运算符。

"1.1" + "1.1" = "1.11.1"
(+"1.1") + (+"1.1") = 2.2   
// 注意:加入括号为清楚起见,不是必需的。

声明变量

var 声明全局变量和局部变量
let 声明块作用域的局部变量
const 声明一个常量

使用 var 和 let 声明的变量时没有赋予初始值的,其值为 undefined,

var a;
console.log("The value of a is" + a); // a 的值是 undefined

console.log("The value of b is" + b);// b 的值是 undefined 
var b;


console.log("The value of c is" + c); // 未捕获的引用错误:c 未被定义

let x;
console.log("The value of x is" + x); // x 的值是 undefined

console.log("The value of y is" + y);// 未捕获的引用错误:y 未被定义
let y;

你可以使用 undefined 来判断一个变量是否已赋值。在以下的代码中,变量 input 未被赋值,因此 if 条件语句的求值结果是 true

var input;
if(input === undefined){doThis();
} else {doThat();
}
  • undefined 值在布尔类型环境中会被当作 false。
  • 数值类型环境中 undefined 值会被转换为 NaN。
  • 当你对一个 null 变量求值时,空值 null 在数值类型环境中会被当作 0 来对待,而布尔类型环境中会被当作 false
  • var n = null;
    console.log(n * 32); // 在控制台中会显示 0

变量的作用域

在函数之外声明的变量,叫做全局变量,因为它可被当前文档中的任何其他代码所访问。在函数内部声明的变量,叫做局部变量,因为它只能在当前函数的内部访问。

ECMAScript 6 之前的 JavaScript 没有 语句块 作用域;相反,语句块中声明的变量将成为语句块所在函数(或全局作用域)的局部变量。例如,如下的代码将在控制台输出 5,因为 x 的作用域是声明了 x 的那个函数(或全局范围),而不是 if 语句块。

if (true) {var x = 5;}
console.log(x); // 5

如果使用 ECMAScript 6 中的 let 声明,上述行为将发生变化。

if (true) {let y = 5;}
console.log(y); // ReferenceError: y 没有被声明

变量提升

JavaScript 变量的另一个不同寻常的地方是,你可以先使用变量稍后再声明变量而不会引发异常。这一概念称为变量提升;JavaScript 变量感觉上是被“提升”或移到了函数或语句的最前面。但是,提升后的变量将返回 undefined 值。因此在使用或引用某个变量之后进行声明和初始化操作,这个被提升的变量仍将返回 undefined 值。

/**
 * 例子 1
 */
console.log(x === undefined); // true
var x = 3;


/**
 * 例子 2
 */
// will return a value of undefined
var myvar = "my value";

(function() {console.log(myvar); // undefined
  var myvar = "local value";
})();


// 详细解释就是
/**
 * 例子 1
 */
var x;
console.log(x === undefined); // true
x = 3;
 
/**
 * 例子 2
 */
var myvar = "my value";
 
(function() {
  var myvar;
  console.log(myvar); // undefined
  myvar = "local value";
})();

由于存在变量提升,一个函数中所有的 var 语句应尽可能地放在接近函数顶部的地方。这个习惯将大大提升代码的清晰度。

在 ECMAScript 6 中,let(const)将不会提升变量到代码块的顶部。因此,在变量声明之前引用这个变量,将抛出引用错误(ReferenceError)。这个变量将从代码块一开始的时候就处在一个“暂时性死区”,直到这个变量被声明为止。

console.log(x); // ReferenceError
let x = 3;

函数提升

对于函数来说,只有函数声明会被提升到顶部,而函数表达式不会被提升。

/* 函数声明 */

foo(); // "bar"

function foo() {console.log("bar");
}


/* 函数表达式 */

baz(); // 类型错误:baz 不是一个函数

var baz = function() {console.log("bar2");
};

常量

你可以用关键字 const 创建一个只读的常量。常量标识符的命名规则和变量相同:必须以字母、下划线(_)或美元符号($)开头并可以包含有字母、数字或下划线。

const PI = 3.14;

常量不可以通过重新赋值改变其值,也不可以在代码运行时重新声明。它必须被初始化为某个值。

常量的作用域规则与 let 块级作用域变量相同。若省略 const 关键字,则该标识符将被视为变量。

在同一作用域中,不能使用与变量名或函数名相同的名字来命名常量。

然而,对象属性被赋值为常量是不受保护的,所以下面的语句执行时不会产生错误。

const MY_OBJECT = {"key": "value"};
MY_OBJECT.key = "otherValue";

同样的,数组的被定义为常量也是不受保护的,所以下面的语句执行时也不会产生错误。

const MY_ARRAY = ['HTML','CSS'];
MY_ARRAY.push('JAVASCRIPT');
console.log(MY_ARRAY); //logs ['HTML','CSS','JAVASCRIPT'];

字面量 (Literals)

译注:字面量是由语法表达式定义的常量;或,通过由一定字词组成的语词表达式定义的常量

在 JavaScript 中,你可以使用各种字面量。这些字面量是脚本中按字面意思给出的固定的值,而不是变量。(译注:字面量是常量,其值是固定的,而且在程序脚本运行中不可更改

数组字面量 (Array literals)

数组字面值是一个封闭在方括号对 ([]) 中的包含有零个或多个表达式的列表,其中每个表达式代表数组的一个元素。当你使用数组字面值创建一个数组时,该数组将会以指定的值作为其元素进行初始化,而其长度被设定为元素的个数。

下面的示例用 3 个元素生成数组 coffees,它的长度是 3。

var coffees = ["French Roast", "Colombian", "Kona"];

var a=[3];

console.log(a.length); // 1

console.log(a[0]); // 3
// 注意 这里的数组字面值也是一种对象初始化器。

若在顶层(全局)脚本里用字面值创建数组,JavaScript 语言将会在每次对包含该数组字面值的表达式求值时解释该数组。另一方面,在函数中使用的数组,将在每次调用函数时都会被创建一次。

数组字面值同时也是数组对象。有关数组对象的详情请参见数组对象一文。

数组字面值中的多余逗号
(译注:声明时)你不必列举数组字面值中的所有元素。若你在同一行中连写两个逗号(,),数组中就会产生一个没有被指定的元素,其初始值是 undefined。以下示例创建了一个名为 fish 的数组:

var fish = ["Lion", , "Angel"];

在这个数组中,有两个已被赋值的元素,和一个空元素(fish[0]是 ”Lion”,fish[1]是 undefined,而 fish[2]是 ”Angel”;译注:此时数组的长度属性 fish.length 是 3)。

如果你在元素列表的尾部添加了一个逗号,它将会被忽略。在下面的例子中,数组的长度是 3,并不存在 myList[3]这个元素(译注:这是指数组的第 4 个元素噢,作者是在帮大家复习数组元素的排序命名方法)。元素列表中其它所有的逗号都表示一个新元素(的开始)。

注意:尾部的逗号在早期版本的浏览器中会产生错误,因而编程时的最佳实践方式就是移除它们。

(译注:而“现代”的浏览器似乎鼓励这种方式,这也很好解释原因。尾部逗号可以减少向数组的最后添加元素时,因为忘记为这最后一个元素加逗号 所造成的错误。)

var myList = ['home', , 'school',];

在下面的例子中,数组的长度是 4,元素 myList[0]和 myList[2]缺失(译注:没被赋值,因而是 undefined)。

var myList = [, 'home', , 'school'];

再看一个例子。在这里,该数组的长度是 4,元素 myList[1]和 myList[3]被漏掉了。(但是)只有最后的那个逗号被忽略。

var myList = ['home', , 'school', ,];

理解多余的逗号(在脚本运行时会被如何处理)的含义,对于从语言层面理解 JavaScript 是十分重要的。但是,在你自己写代码时:显式地将缺失的元素声明为 undefined,将大大提高你的代码的清晰度和可维护性。

布尔字面量 (Boolean literals)

布尔类型有两种字面量:true 和 false。

不要混淆作为布尔对象的真和假与布尔类型的原始值 true 和 false。布尔对象是原始布尔数据类型的一个包装器

整数 (Integers)

整数可以用十进制(基数为 10)、十六进制(基数为 16)、八进制(基数为 8)以及二进制(基数为 2)表示。

  • 十进制整数字面量由一串数字序列组成,且没有前缀 0。
  • 八进制的整数以 0(或 0O、0o)开头,只能包括数字 0 -7。
  • 十六进制整数以 0x(或 0X)开头,可以包含数字(0-9)和字母 a~f 或 A~F。
  • 二进制整数以 0b(或 0B)开头,只能包含数字 0 和 1。

严格模式下,八进制整数字面量必须以 0o 或 0O 开头,而不能以 0 开头。

整数字面量举例:

0, 117 and -345 (十进制, 基数为 10)
015, 0001 and -0o77 (八进制, 基数为 8)
0x1123, 0x00111 and -0xF1A7 (十六进制, 基数为 16 或 ”hex”)
0b11, 0b0011 and -0b11 (二进制, 基数为 2)

对象字面量 (Object literals)

对象字面值是封闭在花括号对 ({}) 中的一个对象的零个或多个 ” 属性名 - 值 ” 对的(元素)列表。你不能在一条语句的开头就使用对象字面值,这将导致错误或产生超出预料的行为,因为此时左花括号({)会被认为是一个语句块的起始符号。(译者:这 里需要对语句 statement、块 block 等基本名词的解释)

以下是一个对象字面值的例子。对象 car 的第一个元素(译注:即一个属性 / 值对)定义了属性 myCar;第二个元素,属性 getCar,引用了一个函数(即 CarTypes(“Honda”));第三个元素,属性 special,使用了一个已有的变量(即 Sales)。

var Sales = "Toyota";

function CarTypes(name) {return (name === "Honda") ?
    name :
    "Sorry, we don't sell "+ name +"." ;
}

var car = {myCar: "Saturn", getCar: CarTypes("Honda"), special: Sales };

console.log(car.myCar);   // Saturn
console.log(car.getCar);  // Honda
console.log(car.special); // Toyota

更进一步的,你可以使用数字或字符串字面值作为属性的名字,或者在另一个字面值内嵌套上一个字面值。如下的示例中使用了这些可选项。

var car = {manyCars: {a: "Saab", "b": "Jeep"}, 7: "Mazda" };

console.log(car.manyCars.b); // Jeep
console.log(car[7]); // Mazda

对象属性名字可以是任意字符串,包括空串。如果对象属性名字不是合法的 javascript 标识符,它必须用 ”” 包裹。属性的名字不合法,那么便不能用. 访问属性值,而是通过类数组标记 (“[]”) 访问和赋值。

var unusualPropertyNames = {"":"An empty string","!":"Bang!"}
console.log(unusualPropertyNames."");   // 语法错误: Unexpected string
console.log(unusualPropertyNames[""]);  // An empty string
console.log(unusualPropertyNames.!);    // 语法错误: Unexpected token !
console.log(unusualPropertyNames["!"]); // Bang!

字符串字面量 (String literals)

字符串字面量是由双引号(”)对或单引号(’)括起来的零个或多个字符。字符串被限定在同种引号之间;也即,必须是成对单引号或成对双引号。下面的例子都是字符串字面值:

"foo"
'bar'
"1234"
"one line \n another line"
"John's cat"

你可以在字符串字面值上使用字符串对象的所有方法——JavaScript 会自动将字符串字面值转换为一个临时字符串对象,调用该方法,然后废弃掉那个临时的字符串对象。你也能用对字符串字面值使用类似 String.length 的属性:

console.log("John's cat".length) 
// 将打印字符串中的字符个数(包括空格)// 结果为:10

在 ES2015 中,还提供了一种模板字符串(template literals),模板字符串提供了一些语法糖来帮你构造字符串。这与 Perl、Python 还有其他语言中的字符串插值(string interpolation)的特性非常相似。除此之外,你可以在通过模板字符串前添加一个 tag 来自定义模板字符串的解析过程,这可以用来防止注入攻击,或者用来建立基于字符串的高级数据抽象。

// Basic literal string creation
`In JavaScript '\n' is a line-feed.`

// Multiline strings
`In JavaScript this is
 not legal.`

// String interpolation
var name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`

// Construct an HTTP request prefix is used to interpret the replacements and construction
POST`http://foo.org/bar?a=${a}&b=${b}
     Content-Type: application/json
     X-Credentials: ${credentials}
     {"foo": ${foo},
       "bar": ${bar}}`(myOnReadyStateChangeHandler);

除非有特别需要使用字符串对象,否则, 你应当始终使用字符串字面值。

js 流程控制与错误处理

条件判断语句

条件判断语句指的是根据指定的条件所返回的结果(真或假或其它预定义的),来执行特定的语句。JavaScript 支持两种条件判断语句:if…else 和 switch。

let iceCream = 'chocolate';
if (iceCream === 'chocolate') {alert('我最喜欢巧克力冰激淋了。');    
} else {alert('但是巧克力才是我的最爱呀……');    
}

异常处理语句

你可以用 throw 语句抛出一个异常并且用 try…catch 语句捕获处理它。

  • throw 语句
  • try…catch 语句

Promises

从 ECMAScript 6 开始,JavaScript 增加了对 Promise 对象的支持,它允许你对延时和异步操作流进行控制。

Promise 对象有以下几种状态:

  • pending:初始的状态,即正在执行,不处于 fulfilled 或 rejected 状态。
  • fulfilled:成功的完成了操作。
  • rejected:失败,没有完成操作。
  • settled:Promise 处于 fulfilled 或 rejected 二者中的任意一个状态, 不会是 pending。

展现了 Promise 的工作流

function imgLoad(url) {return new Promise(function(resolve, reject) {var request = new XMLHttpRequest();
    request.open('GET', url);
    request.responseType = 'blob';
    request.onload = function() {if (request.status === 200) {resolve(request.response);
      } else {
        reject(Error('Image didn\'t load successfully; error code:' 
                     + request.statusText));
      }
    };
    request.onerror = function() {reject(Error('There was a network error.'));
    };
    request.send();});
}

循环和迭代

JavaScript 中提供了这些循环语句:

  • for 语句
  • do…while 语句
  • while 语句
  • labeled 语句
  • break 语句
  • continue 语句
  • for…in 语句
  • for…of 语句

for 语句

一个 for 循环会一直重复执行,直到指定的循环条件为 fasle。JavaScript 的 for 循环和 Java 与 C 的 for 循环是很相似的。

for ([initialExpression]; [condition]; [incrementExpression])
statement

当一个 for 循环执行的时候,会发生以下事件:

  1. 如果有初始化表达式 initialExpression,它将被执行。这个表达式通常会初始化一个或多个循环计数器,但语法上是允许一个任意复杂度的表达式的。这个表达式也可以声明变量。
  2. 计算 condition 表达式的值。如果 condition 的值是 true,循环中的 statement 会被执行。如果 condition 的值是 false,for 循环终止。如果 condition 表达式整个都被省略掉了,condition 的值会被认为是 true。
  3. 循环中的 statement 被执行。如果需要执行多条语句,可以使用块 ({…})来包裹这些语句。
  4. 如果有更新表达式 incrementExpression,执行它.
  5. 然后流程回到步骤 2。
<form name="selectForm">
  <p>
    <label for="musicTypes">Choose some music types, then click the button below:</label>
    <select id="musicTypes" name="musicTypes" multiple="multiple">
      <option selected="selected">R&B</option>
      <option> 爵士 </option>
      <option> 布鲁斯 </option>
      <option> 新纪元 </option>
      <option> 古典 </option>
      <option> 歌剧 </option>
    </select>
  </p>
  <p><input id="btn" type="button" value="选择了多少个选项?" /></p>
</form>

<script>
function howMany(selectObject) {
  var numberSelected = 0;
  for (var i = 0; i < selectObject.options.length; i++) {if (selectObject.options[i].selected) {numberSelected++;}
  }
  return numberSelected;
}

var btn = document.getElementById("btn");
btn.addEventListener("click", function(){alert('选择选项的数量是:' + howMany(document.selectForm.musicTypes))
});
</script>

do…while

do…while 语句一直重复直到指定的条件求值得到假(false)。一个 do…while 语句看起来像这样:

do
  statement
while (condition);

statement 在检查条件之前会执行一次。要执行多条语句(语句块),要使用块语句 ({…}) 包括起来。如果 condition 为真(true),statement 将再次执行。在每个执行的结尾会进行条件的检查。当 condition 为假(false),执行会停止并且把控制权交回给 do…while 后面的语句。

在下面的例子中,这个 do 循环将至少重复一次并且一直重复直到 i 不再小于 5。

do {
  i += 1;
  console.log(i);
} while (i < 5);

while 语句

一个 while 语句只要指定的条件求值为真(true)就会一直执行它的语句块。一个 while 语句看起来像这样:

while (condition)

statement

如果这个条件变为假,循环里的 statement 将会停止执行并把控制权交回给 while 语句后面的代码。

条件检测会在每次 statement 执行之前发生。如果条件返回为真,statement 会被执行并紧接着再次测试条件。如果条件返回为假,执行将停止并把控制权交回给 while 后面的语句。

要执行多条语句(语句块),要使用块语句 ({…}) 包括起来。

例子 1
下面的 while 循环只要 n 小于 3 就会一直执行:

var n = 0;
var x = 0;
while (n < 3) {
  n++;
  x += n;
}

在每次循环里,n 会增加 1 并被加到 x 上。所以,x 和 n 的变化是:

  • 第一次完成后:n = 1 和 x = 1
  • 第二次完成后:n = 2 和 x = 3
  • 第三次完成后:n = 3 和 x = 6

在三次完成后,条件 n < 3 结果不再为真,所以循环终止了。

例子 2
避免无穷循环(无限循环)。保证循环的条件结果最终会变成假;否则,循环永远不会停止。下面这个 while 循环会永远执行因为条件永远不会变成假:

while (true) {console.log("Hello, world");
}

函数

函数 用来封装可复用的功能。如果没有函数,一段特定的操作过程用几次就要重复写几次,而使用函数则只需写下函数名和一些简短的信息

浏览器内置函数和用户定义的函数

定义函数

函数声明

一个函数定义(也称为函数声明,或函数语句)由一系列的 function 关键字组成,依次为:

  • 函数的名称。
  • 函数参数列表,包围在括号中并由逗号分隔。
  • 定义函数的 JavaScript 语句,用大括号 {} 括起来。

例如,以下的代码定义了一个简单的 square 函数:

function square(number) {return number * number;}

函数 square 使用了一个参数,叫作 number。这个函数只有一个语句,它说明该函数将函数的参数(即 number)自乘后返回。函数的 return 语句确定了函数的返回值:


return number * number;

原始参数(比如一个具体的数字)被作为值传递给函数;值被传递给函数,如果被调用函数改变了这个参数的值,这样的改变不会影响到全局或调用函数。

如果你传递一个对象(即一个非原始值,例如 Array 或用户自定义的对象)作为参数,而函数改变了这个对象的属性,这样的改变对函数外部是可见的,如下面的例子所示:

function myFunc(theObject) {theObject.make = "Toyota";}

var mycar = {make: "Honda", model: "Accord", year: 1998};
var x, y;

x = mycar.make;     // x 获取的值为 "Honda"

myFunc(mycar);
y = mycar.make;     // y 获取的值为 "Toyota"
                    // (make 属性被函数改变了)

函数表达式

虽然上面的函数声明在语法上是一个语句,但函数也可以由函数表达式创建。这样的函数可以是匿名的;它不必有一个名称。例如,函数 square 也可这样来定义:

var square = function(number) {return number * number;};
var x = square(4); // x gets the value 16

然而,函数表达式也可以提供函数名,并且可以用于在函数内部代指其本身,或者在调试器堆栈跟踪中识别该函数:

var factorial = function fac(n) {return n<2 ? 1 : n*fac(n-1)};

console.log(factorial(3));

当将函数作为参数传递给另一个函数时,函数表达式很方便。下面的例子演示了一个叫 map 的函数如何被定义,而后使用一个表达式函数作为其第一个参数进行调用:

function map(f,a) {var result = [],i; // 创建一个新数组
  for (i = 0; i != a.length; i++)
    result[i] = f(a[i]);
  return result;
}

下面的代码:

function map(f, a) {var result = []; // 创建一个数组
  var i; // 声明一个值,用来循环
  for (i = 0; i != a.length; i++)
    result[i] = f(a[i]);
      return result;
}
var f = function(x) {return x * x * x;}
var numbers = [0,1, 2, 5,10];
var cube = map(f,numbers);
console.log(cube);

返回 [0, 1, 8, 125, 1000]。

在 JavaScript 中,可以根据条件来定义一个函数。比如下面的代码,当 num 等于 0 的时候才会定义 myFunc:

var myFunc;
if (num == 0){myFunc = function(theObject) {theObject.make = "Toyota"}
}

除了上述的定义函数方法外,你也可以在运行时用 Function 构造器由一个字符串来创建一个函数,很像 eval() 函数。

当一个函数是一个对象的属性时,称之为方法。了解更多关于对象和方法的知识 使用对象。

调用函数

调用函数节
定义一个函数并不会自动的执行它。定义了函数仅仅是赋予函数以名称并明确函数被调用时该做些什么。调用函数才会以给定的参数真正执行这些动作。例如,一旦你定义了函数 square,你可以如下这样调用它:

square(5);
上述语句通过提供参数 5 来调用函数。函数执行完它的语句会返回值 25。

函数一定要处于调用它们的域中,但是函数的声明可以被提升(出现在调用语句之后),如下例:

console.log(square(5));
/* ... */
function square(n) {return n*n}

函数域是指函数声明时的所在的地方,或者函数在顶层被声明时指整个程序。

提示:注意只有使用如上的语法形式(即 function funcName(){})才可以。而下面的代码是无效的。就是说,函数提升仅适用于函数声明,而不适用于函数表达式。

console.log(square); // square is hoisted with an initial value undefined.
console.log(square(5)); // TypeError: square is not a function
var square = function (n) {return n * n;}

函数的参数并不局限于字符串或数字。你也可以将整个对象传递给函数。函数 show_props(其定义参见 用对象编程)就是一个将对象作为参数的例子。

函数可以被递归,就是说函数可以调用其本身。例如,下面这个函数就是用递归计算阶乘:

function factorial(n){if ((n == 0) || (n == 1))
    return 1;
  else
    return (n * factorial(n - 1));
}

你可以计算 1 - 5 的阶乘如下:

var a, b, c, d, e;

a = factorial(1); // 1 赋值给 a
b = factorial(2); // 2 赋值给 b
c = factorial(3); // 6 赋值给 c
d = factorial(4); // 24 赋值给 d
e = factorial(5); // 120 赋值给 e 

还有其它的方式来调用函数。常见的一些情形是某些地方需要动态调用函数,或者函数的实参数量是变化的,或者调用函数的上下文需要指定为在运行时确定的特定对象。显然,函数本身就是对象,因此这些对象也有方法(参考 Function)。作为此中情形之一,apply()方法可以实现这些目的。

函数作用域

在函数内定义的变量不能在函数之外的任何地方访问,因为变量仅仅在该函数的域的内部有定义。相对应的,一个函数可以访问定义在其范围内的任何变量和函数。换言之,定义在全局域中的函数可以访问所有定义在全局域中的变量。在另一个函数中定义的函数也可以访问在其父函数中定义的所有变量和父函数有权访问的任何其他变量。

// 下面的变量定义在全局作用域 (global scope) 中
var num1 = 20,
    num2 = 3,
    name = "Chamahk";

// 本函数定义在全局作用域
function multiply() {return num1 * num2;}

multiply(); // 返回 60

// 嵌套函数的例子
function getScore() {
  var num1 = 2,
      num2 = 3;
  
  function add() {return name + "scored" + (num1 + num2);
  }
  
  return add();}

getScore(); // 返回 "Chamahk scored 5"

作用域和函数堆栈

正文完
 0