找回密码
 立即注册
首页 业界区 业界 Web前端入门第 64 问:JavaScript 几种函数定义方式有什 ...

Web前端入门第 64 问:JavaScript 几种函数定义方式有什么区别?

尸酒岐 2025-6-10 12:29:15
函数 作为 JS 的一等公民,随处可见它的身影。
我理解的它最主要作用就是用来提取重复代码,但凡有 JS 代码需要复制粘贴的时候,那么这时候就可以考虑使用函数封装了。
当函数写在对象中的时候,这时候它变了一个名字,称之为 方法。
function 声明

在使用 function 关键字声明函数时,需注意声明提升问题,意思就是 function 声明的函数,不存在先后顺序,任意位置都可以调用。
  1. function test() {
  2.   console.log('前端路引');
  3. }
  4. test() // 调用函数
复制代码
test 就是函数的名字,函数名的规则和变量声明差不多,只要不是数字和特殊字符开头,语法规则都是允许的,包括都可以使用中文定义函数,虽然不建议这么使用!
  1. function 测试() {
  2.   console.log('前端路引');
  3. }
  4. 测试() // 调用函数
复制代码
声明提升

function 定义的函数会提升到作用域顶部,所以可以在函数定义之前调用,比如:
  1. test() // 此处可以调用 function 声明的函数
  2. const var1 = '前端路引 -- 1'
  3. console.log(var1)
  4. function test() {
  5.   console.log('前端路引 -- 2');
  6. }
复制代码
输出:
  1. 前端路引 -- 2
  2. 前端路引 -- 1
复制代码
包括写在 if 判断中的 function 都会提升到作用域顶部,比如:
  1. test()
  2. if (false) {
  3.   console.log('前端路引 -- 1'); // 此行代码不会执行
  4.   function test() {
  5.     console.log('前端路引 --2');
  6.   }
  7. }
复制代码
输出:
  1. 前端路引 -- 2
复制代码
所以不建议在条件语句中去使用 function 声明函数!
函数表达式

函数表达式就是使用一个变量来保存函数,这种写法有个好处是可以控制定义函数的逻辑。
声明方式:
  1. const test = function() {
  2.   console.log('前端路引');
  3. }
  4. test()
复制代码
表达式声明的函数只能在声明之后调用,如果在声明之前调用,代码会报错:
  1. test() // 报错 ReferenceError: test is not defined
  2. const test = function() {
  3.   console.log('前端路引');
  4. }
复制代码
使用 var 声明时会报错 TypeError: test is not a function:
  1. test() // 报错 TypeError: test is not a function
  2. var test = function() {
  3.   console.log('前端路引');
  4. }
复制代码
在 if 中声明的函数表达式,在外部无法调用:
  1. if (false) {
  2.   const test = function() {
  3.     console.log('前端路引');
  4.   }
  5. }
  6. test() // 报错 ReferenceError: test is not defined
复制代码
箭头函数

箭头函数的声明与函数表达式有些相似,都需要通过变量保存。
声明方式:
  1. const test1 = () => {
  2.   console.log('前端路引');
  3. }
  4. const test2 = (a, b) => a + b; // 单行时候可以省略花括号,直接返回值
  5. // 等价于
  6. // const test2 = (a, b) => {return a + b}
  7. test1() // 输出:前端路引
  8. console.log(test2(1, 2)) // 输出:3
复制代码
箭头函数和函数表达式的区别:

  • 箭头函数自身没有 this 绑定,继承外层作用域的 this。
  1. const test1 = function () {
  2.   console.log(this)
  3. }
  4. const test2 = () => {
  5.   console.log(this)
  6. }
  7. test1.bind({a: '123'})() // 获得对象 {a: '123'}
  8. test2.bind({a: '123'})() // 获得全局对象 window
复制代码

  • 由于没有 this,所以也无法作为构造函数使用,不能使用 new 实例化。
  1. const test1 = function () {
  2.   console.log('前端路引')
  3. }
  4. const test2 = () => {
  5.   console.log('前端路引')
  6. }
  7. new test1()
  8. new test2() // 报错 TypeError: test2 is not a constructor
复制代码

  • 箭头函数也没有 arguments 对象,所以无法通过 arguments 相关方法,比如 arguments.callee 获取函数自身。
  1. const test1 = function () {
  2.   console.log(arguments) // 获取到参数对象
  3. }
  4. const test2 = () => {
  5.   console.log(arguments) // 报错 ReferenceError: arguments is not defined
  6. }
  7. test1('前端路引')
  8. test2('前端路引')
复制代码
生成器函数

ES6 新增的声明方式,常规的业务代码一般很少使用(也可能是我的段位太低~~)。
  1. function* test() {
  2.   yield 1;
  3.   yield 2;
  4. }
  5. const temp = test()
  6. console.log(temp.next()) // 输出:{value: 1, done: false}
  7. console.log(temp.next()) // 输出:{value: 2, done: false}
  8. console.log(temp.next()) // 输出:{value: undefined, done: true}
复制代码
这种方式可以使用 yield 暂停函数执行,多用于异步迭代场景。
看一个异步使用 yield 例子:
  1. function* testAsync() {
  2.   const data = yield new Promise(resolve => {
  3.     setTimeout(() => resolve('Hello World'), 1000); // 模拟异步操作
  4.   });
  5.   console.log(data); // 此处的 data 是 next 传入数据,不是 Promise 返回数据
  6. }
  7. async function run() {
  8.   const generator = testAsync();
  9.   const result = await generator.next().value; // 等待 Promise
  10.   generator.next(result); // 将结果传递回生成器并继续执行
  11. }
  12. run()
复制代码
构造函数 Function 声明

虽然不建议使用这种声明函数,咱们学习了解一下还是没问题的。
  1. const test = new Function('a', 'b', 'return a + b');
  2. console.log(test(1, 2))
复制代码
问题:
1、通过字符串动态生成代码,存在安全风险,容易出现代码注入攻击。
2、每次都会解析字符串,性能会比较低。
写在最后

函数 作为 JS 语言中的一等公民,几种声明方式区别是面试中的常客,经常被问及 箭头函数 与 function 有哪些区别。
函数 是基础,也是函数式编程的核心,必须熟练掌握~~

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册