js中的函数

本质

函数实际上是一个Function对象

函数不定义return默认返回undefined

定义函数方法

有多种方法可以定义函数

函数声明(函数语句)

1
2
3
4
5
function name([param[, param[, ... param]]]) { statements }

function sayHello() {
console.log("Hello");
}

函数表达式

函数表表达式可以看作是把函数作为值的一种用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const sayHi = function greet() {
console.log("Hi");
};

const sayHi = function () {
console.log("Hi");
};

function greet(name, callback) {
console.log("Hello, " + name + "!");
callback(); // 调用传入的函数
}

function sayBye() {
console.log("Goodbye!");
}

// 把 sayBye 函数作为参数传进去
greet("Alice", sayBye);

把函数传给变量,常量当值是函数表达式,传给函数当参数值也是函数表达式

❓:那为什么要具名定义函数呢,既然赋值给变量了,那都写成function (){}不就好了
💡:因为有时会定义递归函数,像是这样

1
2
3
4
5
6
const factorial = function fact(n) {
if (n <= 1) return 1;
return n * fact(n - 1);
};

console.log(factorial(5)); // 120

在写法上这两种非常行接近,区别重要在提升和作用域方面

  • 函数声明定义的函数是可以在定义前调用的,因为在执行前会被提升到当前作用域的顶部,相对的函数表达式不会提升,所以在定义前调用会报错

函数生成器声明

函数生成器表达式

箭头函数表达式

写法

1
2
3
const ceshi = () => {
console.log("nihao");
};

其中括号中的是参数,支持剩余参数、默认参数和解构,始终需要括号

  • 剩余参数
1
2
const f = (a, b, ...r) => [a, b, r];
f(1, 2, 3, 4, 5); // [1, 2, [3, 4, 5]]

其中ab是普通参数,...r表示接受剩余的所有参数,组成一个数组

  • 默认参数

当函数未传入对应参数或是传入undefined时,他将会使用默认的值

1
2
3
4
5
6
7
function foo(a = 100) {
console.log(a);
}

foo(); // 输出 100
foo(undefined); // 输出 100
foo(0); // 输出 0(不会使用默认值)

只有undefined可以,其余的假值是不起作用的
把带默认值的参数放到前面再试图跳过他是不合法的,像是这样

1
2
3
function f(a = 1, b = 2, c = 3) { ... }
f(1, , 3); // ❌ 语法错误
f(1,undefined,3); //必须显式的传递`undefined`

但可以把带默认值的参数放到最后

1
2
3
4
5
function foo(a, b = 20) {
console.log(a, b);
}

foo(10); // ✅ 输出:10 20
  • 解构赋值

    数组解构

    • 基本用法
    1
    2
    3
    4
    5
    const arr = [1, 2, 3];
    const [a, b, c] = arr;
    console.log(a); // 1
    console.log(b); // 2
    console.log(c); // 3
    • 跳过元素
    1
    2
    const [x, , z] = [10, 20, 30];
    console.log(x, z); // 10 30
    • 默认值
    1
    2
    const [a = 100, b = 200] = [1];
    console.log(a, b); // 1 200
    • 嵌套解构
    1
    2
    const [a, [b, c]] = [1, [2, 3]];
    console.log(a, b, c); // 1 2 3

箭头函数没有独立的 thisargumentssuper 绑定,并且不可被用作方法。

this的值取决于它出现的上下文:函数、类或全局

  • 函数上下文
    在函数内部,this 的值取决于函数如何被调用,this的值不是拥有此函数作为自己属性的对象,而是用于调用此函数的对象。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    const obj4 = {
    name: "obj4",
    getThis() {
    return this;
    },
    };
    const obj5 = { name: "obj5" };
    obj6.getThis = obj4.getThis;
    console.log(obj5.getThis()); // { name: 'obj5', getThis: [Function: getThis] }

    普通函数的this是‘调用时决定的’,而箭头函数的this是‘定义时决定的’,永远集成自外层作用域,不能改变

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    const obj = {
    name: "Alice",
    sayHi1: function () {
    console.log(this.name); // this 指向 obj,输出 "Alice"
    },
    sayHi2: () => {
    console.log(this.name); // this 不是 obj,而是外部(window/undefined)
    },
    };
    obj.sayHi1(); // "Alice"
    obj.sayHi2(); // undefined(不是你期望的)

    上面的obj只是一个变量对象,箭头函数从他那里得不到this,只能再往上,也就是全局

arguments同样从上层继承事实上只有函数arguments是一个对应于传递给函数的参数的类数组对象。
官方文档中,推荐编写兼容ES6的代码时使用剩余参数

super从它被定义的上下文获取包含它的类

这三个东西,都要从外层作用域继承,是因为ES6设计箭头函数时,目的就是简洁、闭包友好、绑定外层this,因此:

  • 不创建自己的执行上下文
  • 直接使用它定义时的“父作用域”的上下文
  • 所以,它也就没有自己的 thisargumentssupernew.target

Function构造函数

–TODO: 续写

1


js中的函数
http://example.com/2025/06/15/js中的函数/
作者
prawn
发布于
2025年6月15日
许可协议