JavaScript函数的基本概念

函数是JavaScript中可重复使用的代码块,用于执行特定任务。函数可以接受输入(参数)并返回输出(返回值)。通过将代码封装在函数中,可以实现代码复用、模块化和更好的可维护性。

函数在JavaScript中是一等公民,意味着它们可以像其他数据类型一样被赋值给变量、作为参数传递或从其他函数返回。这种特性使得JavaScript支持函数式编程范式。

函数定义方式

  1. 函数声明:使用function关键字,具有函数名和函数体。函数声明会被提升,可以在定义之前调用。

    function add(a, b) {
      return a + b;
    }
    

  2. 函数表达式:将函数赋值给变量。函数表达式不会被提升,必须在定义后才能调用。

    const add = function(a, b) {
      return a + b;
    };
    

箭头函数

箭头函数(Arrow Function)是ES6引入的语法糖,简化了函数表达式的写法,并具有词法作用域的this特性。其基本语法为:

const func = (param1, param2) => expression;
// 或  
const func = (param1, param2) => { return value; };
  • 单参数时可省略括号:param => expression
  • 无参数时需保留空括号:() => expression
  • 函数体只有单行表达式时,可省略return(隐式返回)。

注:

 1. 不可作为构造函数
箭头函数没有prototype属性,无法通过new调用:

const Foo = () => {};
new Foo(); // TypeError: Foo is not a constructor

2. 无arguments对象
需使用剩余参数替代:

const func = (...args) => console.log(args);

3. 不适用动态this的场景
如对象方法、DOM事件处理器(需显式绑定this时):

button.addEventListener('click', () => {
  console.log(this); // 可能指向全局对象而非button
});


函数使用场景

  1. 事件处理
    用于 DOM 事件监听,如点击、输入等。

    button.addEventListener('click', function() {
      console.log('Button clicked');
    });
    

  2. 异步操作
    回调函数处理异步结果,如 setTimeoutPromise

    setTimeout(() => console.log('Delayed log'), 1000);
    

  3. 模块化开发
    封装功能逻辑,避免全局污染。

    // utils.js
    export function formatDate(date) {
      return date.toISOString();
    }
    

  4. 高阶函数
    接受其他函数作为参数或返回函数的函数。回调函数是作为参数传递给其他函数的函数,常用于异步操作。常见的高阶函数包括 mapfilterreduce 等数组方法。

    const numbers = [1, 2, 3];
    const doubled = numbers.map(num => num * 2); // [2, 4, 6]
     
    


注意事项

  1. 作用域与闭包

    函数创建自己的作用域,内部可以访问外部作用域的变量,但外部不能访问函数内部的变量。这种嵌套作用域的机制形成了闭包。

    闭包是指函数能够记住并访问其词法作用域,即使函数在其词法作用域之外执行。闭包常用于创建私有变量和实现模块模式。

    function createCounter() {
      let count = 0;
      return function() {
        count++;
        return count;
      };
    }
    const counter = createCounter();
    console.log(counter()); // 1
    console.log(counter()); // 2
     
    

  2. this 绑定问题

    函数中的this值取决于调用方式。普通函数的this在严格模式下是undefined,非严格模式下是全局对象。箭头函数继承外层作用域的this

    可以通过callapplybind方法显式设置this值。bind方法创建一个新函数,其this值被永久绑定到指定对象。

    const obj = {
      value: 10,
      logValue: function() {
        console.log(this.value); // 需通过 obj.logValue() 调用
      }
    };
    

  3. 默认参数与剩余参数
    ES6 支持默认参数和 ...rest 语法。

    function greet(name = 'Guest', ...hobbies) {
      console.log(name, hobbies);
    }
    

  4. 避免副作用
    纯函数应避免修改外部状态,依赖仅通过参数传入。

  5. 性能优化
    高频调用的函数可通过节流(Throttle)或防抖(Debounce)优化。


高级特性

  1. 生成器函数(Generator):
    通过 yield 暂停执行,适用于惰性计算。

    function* idGenerator() {
      let id = 0;
      while (true) yield id++;
    }
    

  2. 异步函数(Async/Await):
    简化 Promise 链式调用,代码更线性。

    async function fetchData() {
      const res = await fetch('api/data');
      return res.json();
    }
    


总结与建议

  1. 优先使用箭头函数:简化语法且避免 this 绑定问题,但注意不可作为构造函数。
  2. 避免全局污染:使用模块化(如 export/import)或 IIFE(立即调用函数表达式)隔离作用域。
  3. 性能优化:减少嵌套函数和闭包的使用,避免内存泄漏。
  4. 代码可读性:为函数和参数命名时需清晰表达意图,复杂逻辑添加注释。
  5. 代码拆分:将复杂逻辑拆分为多个小函数,提升可读性和可测试性。

JavaScript函数灵活多样,适用于事件处理、数据操作和异步编程等场景。合理使用箭头函数、默认参数和纯函数能提升代码质量。注意作用域和this绑定问题,并通过拆分逻辑、缓存结果优化性能。

Logo

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

更多推荐