1. 普通函数与箭头函数

1.1 普通函数(Function Declaration / Function Expression)

常见两种写法:

function myFunction() {}

const myFunction = function() {}

普通函数有以下特性:

  • 拥有自己的 this
  • this 的指向根据“调用者”决定
  • 可以作为构造函数使用(可被 new
  • 拥有 arguments 对象

1.2 箭头函数(Arrow Function)

写法简洁:

const my = () => {}

其本质是:一个没有自己 this 的匿名函数。其特点:

  • 没有自己的 this
  • this 完全继承外层作用域的 this
  • 不能用作构造器(不能 new
  • 没有 arguments
  • 在回调、Promise 中极为常用

示例:

const add = (a, b) => a + b;
console.log(add(1,2))

2. 回调函数(Callback)

回调函数是指:把一个函数作为参数传入另一个函数中,由后者在适当时机执行。

示例:

function doSomething(callback) {
  console.log('callback前')
  callback();
  console.log('callback前')
}

doSomething(() => {
  console.log("callback executed");
});

回调常用于监听事件、处理异步行为等。


3. 回调地狱(Callback Hell)

随着回调嵌套层级加深,会出现结构混乱难以维护的现象:

a(() => {
  b(() => {
    c(() => {
      d(() => {
        console.log("done");
      });
    });
  });
});

为解决这个问题,Promise 被引入。


4. Promise 对象

Promise 是一个用于表示异步结果的对象,有三种状态:

  • pending(进行中)
  • fulfilled(已成功)
  • rejected(已失败)

基本用法:

const p = new Promise((resolve, reject) => {
  setTimeout(() => resolve("done"), 1000);
});

p.then(result => console.log(result));

Promise 可以避免回调地狱,使链式调用更优雅:

p.then(r1 => step2(r1))
 .then(r2 => step3(r2))
 .catch(err => console.log(err));

5. async / await

async/await 是 Promise 的语法糖,使异步代码看起来像同步写法。

5.1 async

一个被声明为 async 的函数,返回一个 Promise

async function test() {
  return 123;
}

console.log(test()); // Promise { 123 }

5.2 await

await 用于等待 Promise 的结果,只能在 async 函数中使用。

function wait(ms) {
  return new Promise(resolve => {
    setTimeout(() => resolve("done"), ms);
  });
}

async function test() {
  console.log("start");
  const res = await wait(1000);
  console.log("end", res);
}

test();

执行顺序:

  1. 输出 start
  2. 等待 1 秒
  3. 输出 end done

5.3 async 返回的Promise是什么,await有什么用

async 返回的是被promise括号包起来的一个对象
await可以自动解包

async function test() {
  return {"age":123};
}

async 会自动等价转换为:return Promise.resolve({age:123});
如何使用呢?

✔ 方法 1:用 await(推荐)

async function test() {
  return {"age":123,"id":1};
}

async function main() {
  const data = await test();
  console.log(data.age);
}

main();

✔ 方法 2:用 .then() 获取 Promise 结果

test().then(data => {
  console.log(data.age);
});

✔ 方法 3:立即执行 async 函数

(async () => {
  console.log((await test()).age);
})();

6. 普通函数 vs 箭头函数:this 指向区别

6.1 普通函数的 this:动态绑定

this 取决于“调用方式”:

const obj = {
  name: "A",
  f: function() {
    console.log(this.name); // A
  }
};

obj.f();

6.2 箭头函数的 this:静态绑定(继承外层作用域)

const obj = {
  name: "A",
  f: () => {
    console.log(this.name); // undefined
  }
};

obj.f();

因为箭头函数不会创建自己的 this,它的 this 来自外围作用域(通常是全局环境)。


7. 为什么 setInterval 中普通函数的 this 会丢失?

function Person() {
  this.age = 0;

  setInterval(function() {
    this.age++; // this 指向全局对象,而不是 Person
  }, 1000);
}

因为普通函数的 this 由调用者决定,此时调用者不是 Person 实例。

使用箭头函数修复:

function Person() {
  this.age = 0;

  setInterval(() => {
    this.age++; // 继承外层作用域 this(Person 实例)
  }, 1000);
}

8. 总结

概念 特点
普通函数 有自己的 this,调用方式决定 this,能 new,能使用 arguments
箭头函数 无 this、无 arguments、不可 new,继承外层作用域的 this
回调函数 将函数作为参数传入另一个函数
Promise 解决异步与回调地狱问题,可链式调用
async/await Promise 的语法糖,使异步像同步
this 区别 普通函数:动态绑定;箭头函数:静态继承

通过理解这些概念,你就掌握了 JavaScript 函数与异步机制的核心知识,为进一步深入前端开发打下坚实基础。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐