JavaScript Functions详解(包含ES6箭头函数)

本文围绕JavaScript中的函数展开,介绍了函数的基本概念,包括其可接受参数、返回值等特性。还阐述了函数的句法,如常规函数、箭头函数等。此外,对函数的参数、返回值、嵌套函数、对象方法等方面进行了详细说明,同时提及了IIFE和Function挂载等内容。

简介

JavaScript中的所有内容都发生在函数中。

函数是一个代码块,可以定义一次并随时运行。

函数可以选择接受参数,并返回一个值。

JavaScript中的函数是对象,一种特殊的对象:函数对象。

另外,函数被称为第一类函数,因为它们可以被赋值给一个值,它们可以作为参数传递并用作返回值。

句法

让我们从“旧的”,ES6 / ES2015之前的语法开始。这是一个函数声明:

function dosomething(foo) {
  // do something
}

(现在,在ES6 / ES2015世界中,被称为常规函数)

函数可以分配给变量(这称为函数表达式):

const dosomething = function(foo) {
  // do something
}

命名函数表达式类似,但在堆栈调用跟踪中更好用,这在发生错误时很有用 - 它保存函数的名称:

const dosomething = function dosomething(foo) {
  // do something
}

ES6 / ES2015引入了箭头函数,在使用内联函数时,特别适合用作参数或回调函数:

const dosomething = foo => {
  //do something
}

箭头函数与上面的其他函数定义有很大的不同,我们稍后会解释。

参数

一个函数可以有一个或多个参数。

const dosomething = () => {
  //do something
}

const dosomethingElse = foo => {
  //do something
}

const dosomethingElseAgain = (foo, bar) => {
  //do something
}

从ES6 / ES2015开始,函数可以具有参数的默认值:

const dosomething = (foo = 1, bar = 'hey') => {
  //do something
}

这允许您在不填充所有参数的情况下调用函数:

dosomething(3)
dosomething()

ES2018引入了参数的尾随逗号,这个功能有助于减少因移动参数时丢失逗号而导致的错误(例如,移动中间的最后一个):

const dosomething = (foo = 1, bar = 'hey') => {
  //do something
}

dosomething(2, 'ho!')

您可以将所有参数包装在一个数组中,并在调用函数时使用spread运算符:

const dosomething = (foo = 1, bar = 'hey') => {
  //do something
}
const args = [2, 'ho!']
dosomething(...args)

当使用许多参数的时候,记住这些参数可能很困难。这里可以使用对象,解构保留参数名称:

const dosomething = ({ foo = 1, bar = 'hey' }) => {
  //do something
  console.log(foo) // 2
  console.log(bar) // 'ho!'
}
const args = { foo: 2, bar: 'ho!' }
dosomething(args)

返回值

每个函数都返回一个值,默认情况下为“undefined”。

clipboard.png

任何函数在其代码行结束时,或者当执行流找到return关键字时终止。

当JavaScript遇到此关键字时,它退出函数执行并将控制权交还给其调用者。

如果传递一个值,则该值将作为函数的结果返回:

const dosomething = () => {
  return 'test'
}
const result = dosomething() // result === 'test'

您只能返回一个值。

要_模拟_返回多个值,您可以返回对象文字或数组,并在调用时使用解构赋值功能。

使用数组:

clipboard.png

使用对象:

clipboard.png

嵌套函数

可以在其他函数中定义函数:

const dosomething = () => {
  const dosomethingelse = () => {}
  dosomethingelse()
  return 'test'
}
嵌套函数的作用域是外部函数,不能从外部调用。

对象方法

当用作对象属性时,函数称为方法:

const car = {
  brand: 'Ford',
  model: 'Fiesta',
  start: function() {
    console.log(Started)
  }
}

car.start()

箭头函数中的this

当箭头函数与常规函数用作对象方法时,有一个重要的行为。考虑这个例子:

const car = {
  brand: 'Ford',
  model: 'Fiesta',
  start: function() {
    console.log(Started ${this.brand} ${this.model})
  },
  stop: () => {
    console.log(Stopped ${this.brand} ${this.model})
  }
}

stop()方法不能像你期望的那样工作。

clipboard.png

这是因为this的处理在两个函数声明样式中是不同的。箭头函数中的this指的是封闭函数上下文,在本例中是window对象

clipboard.png

this,使用function()引用宿主对象

这意味着箭头函数不适合用于对象方法和构造函数(箭头函数构造函数实际上会在调用时引发TypeError)。

IIFE,立即调用函数表达式

IIFE是一个在声明后立即执行的功能:

;(function dosomething() {
  console.log('executed')
})()

您可以将结果分配给变量:

const something = (function dosomething() {
  return 'something'
})()

它们非常方便,因为您无需在定义后单独调用该函数。

Function 挂载

执行代码之前的JavaScript会根据某些规则对其进行重新排序。

会将函数移动到其范围的顶部。这就是下面例子不会报错的原因;

dosomething()
function dosomething() {
  console.log('did something')
}

clipboard.png

在内部,JavaScript在调用之前移动函数,以及在同一范围内找到的所有其他函数:

function dosomething() {
  console.log('did something')
}
dosomething()

现在,如果你使用命名函数表达式,因为你正在使用变量,会发生不同的事情。变量声明被提升,但不是值,因此不是函数。

dosomething()
const dosomething = function dosomething() {
  console.log('did something')
}

不会工作:

clipboard.png

这是因为内部发生的事情是:

const dosomething
dosomething()
dosomething = function dosomething() {
  console.log('did something')
}

“let”声明也是如此。var声明也不起作用,但是报的不是同样的错误:

clipboard.png

这是因为var声明被提升并用undefined作为值初始化,而constlet被提升但未初始化。

<think>我们正在讨论JavaScriptES6+的新特性,特别是箭头函数、Promise和async/await。用户已经提供了一些引用,但我们要注意,这些引用主要涉及async/await和Promise,而箭头函数没有直接引用。不过,我们可以结合自己的知识来全面回答。回答结构:1.箭头函数:介绍语法、特性、使用场景和示例。2.Promise:介绍概念、状态、基本用法(创建、链式调用、错误处理)和示例。3.async/await:介绍概念、与Promise的关系、错误处理(try-catch)、示例。注意:用户提供的引用中提到了async/await中如果await后面的Promise变为reject,则后续代码不会执行(引用[1]),以及使用try-catch处理异常(引用[2][3][5]),还有async/await让代码更清晰(引用[5])。这些点需要在async/await部分强调。我们将按照以下方式组织:一、箭头函数(ArrowFunctions)二、Promise三、async/await每个部分都包含基本用法和示例。同时,在最后生成相关问题。开始回答:</think>### JavaScript ES6+ 新特性详解箭头函数、Promise 和 async/await #### 一、箭头函数(Arrow Functions) **核心特性**: - 简洁的 `() => {}` 语法 - 自动绑定词法作用域的 `this` - 无独立的 `arguments` 对象 - 不能作为构造函数使用 **使用场景**: ```javascript // 1. 简化回调 const numbers = [1, 2, 3]; const squares = numbers.map(n => n * n); // [1, 4, 9] // 2. 绑定词法 this function Timer() { this.seconds = 0; setInterval(() => { this.seconds++; // this 正确指向 Timer 实例 }, 1000); } // 3. 隐式返回值 const sum = (a, b) => a + b; // 等效 return a+b ``` #### 二、Promise **核心概念**: - 三种状态:`pending`(进行中)、`fulfilled`(已成功)、`rejected`(已失败) - 链式调用解决回调地狱 **基本用法**: ```javascript // 1. 创建 Promise const fetchData = new Promise((resolve, reject) => { setTimeout(() => Math.random() > 0.5 ? resolve("数据加载成功") : reject(new Error("请求超时")) , 1000); }); // 2. 链式调用 fetchData .then(data => { console.log(data); // "数据加载成功" return processData(data); // 返回新 Promise }) .then(processedData => { console.log(processedData); }) .catch(error => { console.error("捕获错误:", error); // 统一错误处理 }) .finally(() => { console.log("请求结束"); // 无论成功失败都会执行 }); ``` **进阶方法**: ```javascript // 并行执行 Promise.all([ fetch('/api/users'), fetch('/api/products') ]).then(([users, products]) => { console.log(users, products); }); // 竞速执行 Promise.race([ fetch('/api/main'), timeout(2000) // 自定义超时函数 ]).then(firstResult => { console.log(firstResult); }); ``` #### 三、async/await(基于 Promise 的语法糖) **核心优势**: - 用同步写法处理异步操作 - 内置错误处理机制 - 避免回调地狱,提升可读性 **基础用法**: ```javascript async function loadUserProfile(userId) { try { const user = await fetch(`/api/users/${userId}`); const posts = await fetch(`/api/posts?user=${userId}`); return { user, posts }; } catch (error) { console.error("加载失败:", error); throw error; // 重新抛出错误 } } // 调用示例 loadUserProfile(123) .then(profile => console.log(profile)) .catch(err => console.error("外部捕获:", err)); ``` **关键注意事项**: 1. **错误处理**:必须用 `try-catch` 捕获异常 ```javascript async function criticalTask() { try { await Promise.reject("致命错误"); // 触发 catch } catch (err) { console.error("已处理:", err); // 输出"已处理: 致命错误" } } ``` 2. **并行优化**:使用 `Promise.all` 避免串行等待 ```javascript async function loadDashboard() { const [user, settings] = await Promise.all([ fetch('/api/user'), fetch('/api/settings') ]); return { user, settings }; } ``` 3. **顶层 await**(ES2022): ```javascript // 模块顶层直接使用 const config = await fetch('/api/config'); export default config; ``` #### 四、综合应用示例 ```javascript // 箭头函数 + Promise + async/await const fetchResource = async (url, timeout = 5000) => { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), timeout); try { const response = await fetch(url, { signal: controller.signal }); clearTimeout(timeoutId); return response.json(); } catch (err) { if (err.name === 'AbortError') { throw new Error(`请求超时: ${url}`); } throw err; } }; // 使用示例 fetchResource('https://api.example.com/data') .then(data => console.log(data)) .catch(err => console.error(err)); ``` > **最佳实践总结**: > 1. 简单异步操作使用 **Promise 链式调用** > 2. 复杂异步逻辑用 **async/await** 提升可读性[^3][^5] > 3. 并行请求优先 **Promise.all** 提升性能[^4] > 4. 始终用 **try-catch** 处理 async 函数错误[^2][^3] > 5. 避免在 async 函数中遗漏 `await`(导致非预期并行)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值