八、函数
函数是可重用的代码块,只有在被调用时才会执行。它们允许开发人员将他们的脚本分成更小的部分,更容易理解和重用。
定义函数
要创建一个函数,可以使用 function 关键字,后跟一个名称、一组括号和一个代码块。函数的命名惯例与变量相同——使用一个描述性的名称,除了第一个单词以外,每个单词都要大写。
function myFunc()
{
document.write("Hello World");
}
这个函数只是向 web 文档显示一个文本字符串。函数代码块可以包含任何 JavaScript 代码,包括其他函数定义。
调用函数
一旦定义了一个函数,就可以在文档的任何地方调用它,只需键入它的名字,后面加上一组括号。函数名区分大小写,所以字母的大小写需要一致。
myFunc(); // "Hello World"
即使函数定义稍后出现在脚本中,也可以调用函数。这是因为 JavaScript 中的声明是在代码执行之前处理的。
foo(); // ok
function foo() {}
函数参数
函数名后面的括号用于向函数传递参数。为此,必须首先将相应的参数添加到函数的参数列表中。这些参数可以作为常规变量在函数中使用。
function sum(a, b) {
var sum = a + b;
console.log(sum);
}
一个函数可以被定义为接受任意数量的参数。调用该函数时,参数以逗号分隔列表的形式提供。在此示例中,该函数接受两个数值参数,并显示它们的总和。
sum(2, 3); // "5"
像变量一样,函数参数也没有在声明中指定类型。因此,不会自动执行类型检查,函数参数也不限于任何特定的数据类型。
可变参数列表
允许调用一个函数,其参数个数与定义的参数个数不同。如果调用函数时使用的参数较少,那么剩余的参数将被设置为未定义。
function say(message) {
console.log(message);
}
say(); // "undefined"
当调用一个函数的参数比它的定义中的多时,多余的参数将没有名字。可以通过类似数组的 arguments 对象引用这些额外的参数,该对象包含传递给函数的所有参数。
function say() {
console.log(arguments[0]);
}
say("Hello"); // "Hello"
arguments 对象可用于创建 varadic 函数,这些函数能够处理不同数量的参数。举个例子,可以将任意数量的参数传递给下面的函数。该函数遍历参数,并将它们组合成一个字符串,输出到控制台。
function combine() {
var result = "";
for (var i = 0; i < arguments.length; i++) {
result += arguments[i];
}
console.log(result);
}
combine(1, 2, 3); // "123";
返回语句
Return 是一个跳转语句,它使函数退出,并将指定的值返回到调用该函数的地方。举例来说,下面的函数返回其两个参数的和。这个函数又可以作为参数传递给另一个函数,在那里它将计算出结果数。
function getSum(a, b) {
return a + b; // exit function and return value
}
console.log( getSum(1, 2) ); // "3"
return 语句也可以用来在到达 end 块之前退出函数,而不返回任何特定的值。没有返回值的函数将隐式返回 undefined。
function foo() {
return; // exit function
}
console.log( foo() ); // "undefined"
就像变量和参数一样,返回值不进行类型检查。函数需要被适当地文档化,以便函数的用户知道他们的输入和输出应该是什么。
参数传递
参数通过值传递给函数。对于基本类型,这意味着只有值的副本被传递给函数。因此,以任何方式更改参数都不会影响原始变量。
function set(y) {
y = 1;
}
var x = 0;
set(x); // copy of value passed
console.log(x); // "0"
当对象类型用作参数时,传递的是对该对象的引用。这允许函数对原始对象的属性进行更改。
function addFruit(basket) {
basket[0] = "Apple";
}
var fruits = [];
addFruit(fruits); // copy of reference passed
console.log( fruits[0] ); // "Apple"
将新对象赋给参数不会影响函数外部的原始对象。这是因为赋值改变了参数的值,而不是对象的一个属性值。
function makeFruit(basket) {
basket = [ "Apple" ];
}
var fruits = [];
makeFruit(fruits);
console.log( fruits[0] ); // "undefined"
函数表达式
JavaScript 中的函数是对象,特别是函数对象。因此,它们可以被赋给变量并传递给其他函数,就像任何其他对象一样。当一个函数以这种方式使用时,它被称为函数表达式,而不是函数声明。可以使用正常的赋值语法(包括分号)将函数表达式赋给变量。
var say = function foo(message)
{
console.log("Hello " + message);
};
当调用一个函数对象时,引用的是变量名而不是函数名。
say("World"); // "Hello World"
可以在函数内部使用函数名来引用它自己,但是函数名在其他情况下是不必要的。因此,该名称通常被省略。然后,函数表达式被称为匿名函数。
var say = function(message)
{
console.log("Hello " + message);
};
函数表达式通常被用作回调函数,或者被传递给其他函数,或者从其他函数返回。它们允许非常简洁地编写代码,因为函数可以内联,而不必在其他地方定义它。为了说明这一点,下面的例子使用了window.setTimeout
函数,它采用另一个函数和一个数字作为参数。该数字指定在调用函数参数之前等待的毫秒数。
// Call anonymous function after one second
window.setTimeout(function() { console.log("Hello") }, 1000);
范围和寿命
变量的作用域指的是可以使用该变量的代码区域。JavaScript 中的变量既可以全局声明,也可以局部声明。全局变量是在任何函数之外声明的,可以从文档中的任何地方访问。另一方面,局部变量是在函数内部声明的,并且只能在该函数内部访问。
var globalVar = 0; // global variable
function foo() {
var localVar = 0; // local variable
}
局部变量的生存期是有限的。全局变量将在脚本运行期间保持分配状态,而局部变量将在其函数执行完毕后被销毁。
console.log(globalVar); // "0"
foo();
console.log(localVar); // throws a ReferenceError
当作用域中的两个变量同名时,就会出现名称冲突。更多的内部作用域具有优先权,因此最里面的作用域具有最高的优先权,而最外面的作用域具有最低的优先权。
var a = "global";
function foo() {
var a = "local"; // overshaddows global variable
console.log(a);
}
foo(); // "local"
console.log(a); // "global"
与许多其他语言不同,JavaScript 中的代码块没有自己的作用域。因此,在控制结构代码块(如循环或条件语句)中定义的变量在代码块结束时不会被销毁。
if(true) {
var x = 10; // global variable
}
console.log(x); // "10"
还有一种创建变量的替代方法,即在不使用 var 关键字的情况下为未声明的变量赋值。这将隐式地将变量声明为全局变量,即使它是在函数中声明的。
function foo() {
a = 5; // global variable
}
foo();
console.log(a); // "5"
以这种方式错误地引入或覆盖全局变量是常见的错误来源。因此,建议始终使用 var 关键字显式声明变量。
var a = 10;
foo(); // replaces value of global variable
console.log(a); // "5"
像函数声明一样,显式变量声明也在脚本执行之前进行处理。因此,变量可以在声明之前在代码中引用。
console.log(a); // "undefined"
var a = "defined";
console.log(a); // "defined"
对于隐式声明的变量来说,这种行为是不同的,因为在为变量赋值的代码运行之前,这些变量是不存在的。
console.log(b); // throws a ReferenceError
b = "defined"; // never executes
版权属于:月萌API www.moonapi.com,转载请注明出处