Skip to content

8. 函数

Image

8.1. 脚本 [func-01]

该脚本关注函数参数的传递方式:

  • 数值、字符串和布尔值采用值传递;
  • 数组、字面量对象和函数采用引用传递;

'use strict';
// 函数参数传递模式
// -----------------------参数个数 - 按值传递
function doSomethingWithNumber(param) {
  param++;
  console.log("[param inside function]=", param, "[type]=", typeof (param), "[passage par référence]=", param === count);
}
// 调用代码
let count = 10;
doSomethingWithNumber(count);
console.log("[count outside function]=", count);

// --------------------- 字符串 - 按值传递
function doSomethingWithString(param) {
  param += " xyz"
  console.log("[param inside function]=", param, "[type]=", typeof (param), "[passage par référence]=", param === text);
}
// 调用代码
let text = "abcd";
doSomethingWithString(text);
console.log("[text outside function]=", text);

// --------------------- 布尔值 - 按值传递
function doSomethingWithBoolean(param) {
  param = !param;
  console.log("[param inside function]=", param, "[type]=", typeof (param), "[passage par référence]=", param === bool);
}
// 调用码
let bool = true;
doSomethingWithBoolean(bool);
console.log("bool [outside function]=", bool);

// --------------------- 数组 - 按引用传递
function doSomethingWithArray(param) {
  param.push(1000);
  console.log("[param inside function]=", param, "[type]=", typeof (param), "[passage par référence]=", param === tab);
}
// 调用码
const tab = [10, 20, 30];
doSomethingWithArray(tab);
console.log("[tab outside function]=", tab);

// --------------------- 对象 - 按引用传递
function doSomethingWithObject(param) {
  param.unePropriétéNouvelle = "xyz";
  console.log("[param inside function]=", param, "[type]=", typeof (param), "[passage par référence]=", param === obj);
}
// 调用代码
const obj = [10, 20, 30];
doSomethingWithObject(obj);
console.log("[obj outside function]=", obj);

// --------------------- 函数 - 按引用传递
function doSomethingWithFunction(param) {
  // 虽然有点奇怪,但确实有效
  param.unePropriétéNouvelle = "xyz";
  console.log("[param inside function]=", param, "[type]=", typeof (param), "[passage par référence]=", param === f);
}
// 调用代码
const f = x => x + 4;
doSomethingWithFunction(f);
console.log("[f outside function]=", f, f.unePropriétéNouvelle, typeof (f));

执行


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\fonctions\func-01.js"
[param inside function]= 11 [type]= number [passage par référence]= false
[count outside function]= 10
[param inside function]= abcd xyz [type]= string [passage par référence]= false
[text outside function]= abcd
[param inside function]= false [type]= boolean [passage par référence]= false
bool [outside function]= true
[param inside function]= [ 10, 20, 30, 1000 ] [type]= object [passage par référence]= true
[tab outside function]= [ 10, 20, 30, 1000 ]
[param inside function]= [ 10, 20, 30, 'unePropriétéNouvelle': 'xyz' ] [type]= object [passage par référence]= true
[obj outside function]= [ 10, 20, 30, 'unePropriétéNouvelle': 'xyz' ]
[param inside function]= x => x + 4 [type]= function [passage par référence]= true
[f outside function]= x => x + 4 xyz function

8.2. 脚本 [func-02]

以下脚本表明,类型 [function] 与其他数据类型一样,变量可以采用该类型。它还展示了定义函数的两种方法:

  • 一种使用关键字 [function]
  • 另一种使用“箭头”语法 =>;

'use strict';
// 可以将函数赋值给变量
const variable1 = function (a, b) {
  return a + b;
};
console.log("typeof(variable1)=", typeof (variable1));
// 该变量随后可作为函数使用
console.log("variable1(10,12)=", variable1(10, 12));
// 函数定义可以使用 => 语法
const variable2 = (a, b, c) => {
  return a - b + c;
};
console.log("variable2(10,12,14)=", variable2(10, 12, 14));
// 如果函数体内只有一个表达式,可以省略大括号
// 此时该表达式即为函数的返回值
const variable3 = (a, b, c) => a + b + c;
console.log("variable3(10,12,14)=", variable3(10, 12, 14));

执行


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\fonctions\func-02.js"
typeof(variable1)= function
variable1(10,12)= 22
variable2(10,12,14)= 12
variable3(10,12,14)= 36

8.3. 脚本 [func-03]

本脚本探讨了将一个函数作为参数传递给另一个函数的可能性。这种方法在JavaScript框架中被广泛使用。


'use strict';
// 函数的参数可以是 [fonction] 类型

// 函数 f1
function f1(param1, param2) {
  return param1 + param2 + 10;
}
// 函数 f2
function f2(param1, param2) {
  return param1 + param2 + 20;
}
// 函数 g 带函数 f 作为参数
function g(param1, param2, f) {
  return f(param1, param2) + 100;
}
// g 的调用
console.log(g(0, 10, f1));
console.log(g(0, 10, f2));
// 函数类型的实际参数可以直接传递 - 形式 1
console.log(g(0, 10, (param1, param2) => {
  return param1 + param2 + 30;
}));
// 函数类型的实际参数可以直接传递 - 形式 2
console.log(g(0, 10, function (param1, param2) {
  return param1 + param2 + 40;
}));

执行


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\fonctions\func-03.js"
120
130
140
150

8.4. 脚本 [func-04]

以下脚本展示了 JavaScript 函数可以像类一样工作:


'use strict';
// 函数可作为对象使用

// 一个空壳
function f() {

}
// 其属性由外部赋值
f.prop1 = "val1";
f.show = function () {
  console.log(this.prop1);
}
// 使用 f
f.show();

// 一个作为类运行的函数 g
function g() {
  this.prop2 = "val2";
  this.show = function () {
    console.log(this.prop2);
  }
}
// 使用 [new] 实例化该函数
new g().show();

注释

  • 第 5-7 行:函数 f 的主体未定义任何属性;
  • 第 9-12 行:从外部为函数 f 赋予属性;
  • 第 14 行:调用函数(对象)f。请注意,这里不是写 [f()],而是简单地写 [f]。这是一种对象的表示法;
  • 第 17-22 行:定义函数 [g],如同定义一个带有属性和方法的类;
  • 第 24 行:函数 [g][new g()] 实例化;

执行结果


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\classes\class-00.js"
val1
val2

ES6引入了类概念,这使我们今后无需通过函数即可直接使用类。

8.5. 脚本 [func-05]

脚本 [func-05] 展示了名为 [rest operator] 的运算符的使用方法:


'use strict';
// rest 运算符
function f(arg1, ...otherArgs) {
  // 第一个参数
  console.log("arg1=", arg1);
  // 其余参数
  let i = 0;
  otherArgs.forEach(element => {
    console.log("otherArguments[", i, "]=", element);
    i++;
  });
}

// 调用
f(1, "deux", "trois", { x: 2, y: 3 })
  • 第 3 行:[...otherArgs] 的语法使得当调用 f(param1, param2, param3) 时,第 3 行将变为:
    • arg1=param1
    • otherArgs=[param2, param3]。因此,[otherArgs]是一个数组,它汇集了传递给[param1]的所有有效参数;

应用程序的结果如下:

1
2
3
4
arg1= 1
otherArguments[ 0 ]= deux
otherArguments[ 1 ]= trois
otherArguments[ 2 ]= { x: 2, y: 3 }