当前位置: 首页 > news >正文

JavaScript函数详解

目录

一、函数的基础概念

1. 函数的定义方式

2. 函数的参数处理

3.匿名函数与立即执行函数

4.同名函数与函数提升

二、函数的作用域与闭包

1. 作用域(Scope)

2. 闭包(Closure)

三、高阶函数与函数式编程

1. 高阶函数

2. 纯函数

四、this 绑定与箭头函数

1. this 的指向规则

2. 箭头函数的 this

五、异步函数与生成器

1. 回调函数与异步模式

2. Promise 与 async/await

3. 生成器函数(Generator)

六、函数的高级技巧

1. 柯里化(Currying)

2. 防抖(Debounce)与节流(Throttle)

七、总结


一、函数的基础概念

1. 函数的定义方式

JavaScript 函数可通过多种方式定义,每种方式有不同的使用场景和特性。

方式语法特点
函数声明function name() { ... }存在函数提升,可先调用后声明
函数表达式const name = function() { ... }无提升,可匿名或命名
箭头函数const name = () => { ... }无 thisarguments,不可作为构造函数
构造函数new Function('a', 'b', 'return a + b')动态生成函数,慎用(性能和安全问题)

示例

// 函数声明
function add(a, b) { return a + b; }

// 函数表达式
const multiply = function(a, b) { return a * b; };

// 箭头函数
const square = x => x * x;

// 构造函数(极少用)
const subtract = new Function('a', 'b', 'return a - b');

2. 函数的参数处理

JavaScript 函数的参数具有高度灵活性,支持默认值、剩余参数和解构赋值。

特性语法说明
默认参数function(a = 1, b = 2) { ... }ES6+ 支持,参数未传递时使用默认值
剩余参数function(...args) { ... }将剩余参数合并为数组
参数解构function({ x, y }) { ... }从对象或数组中提取值

参数数量不匹配

  • 实参多于形参:多余参数被忽略(可通过 arguments 或剩余参数获取)。

  • 实参少于形参:缺失的形参值为 undefined

示例

// 默认参数
function greet(name = "Guest") {
  console.log(`Hello, ${name}!`);
}

// 剩余参数
function collect(a, ...rest) {
  console.log(rest); // 收集剩余实参为数组
}
collect(1, 2, 3); // rest = [2, 3]

// 参数解构
function printCoordinates({ x, y }) {
  console.log(`X: ${x}, Y: ${y}`);
}
printCoordinates({ x: 10, y: 20 }); // X: 10, Y: 20

3.匿名函数与立即执行函数

1. 匿名函数

  • 定义:无名称的函数,通常作为回调或函数表达式。

    const square = function(x) { return x * x; }; // 匿名函数表达式
    setTimeout(function() { console.log('Done'); }, 1000); // 回调

2. 立即执行函数(IIFE)

  • 作用:创建独立作用域,避免污染全局命名空间。

  • 写法

    (function(){ xxx  })();
    (function(){xxxx}());
    (function() {
      const privateVar = '内部变量';
      console.log(privateVar);
    })();
    
    // 带参数
    (function(a, b) {
      console.log(a + b);
    })(3, 5); // 输出 8
  • 现代替代方案(ES6 块作用域 + let/const):

    {
      const privateVar = '内部变量';
      console.log(privateVar);
    }

4.同名函数与函数提升

1. 函数声明提升(Hoisting)

  • 后声明的同名函数会覆盖前面的:

    console.log(sayHello()); // "Later Hello"
    
    function sayHello() { return "Early Hello"; }
    function sayHello() { return "Later Hello"; } // 覆盖前者

2. 函数表达式无提升

  • 按代码顺序执行:

    console.log(sayHello()); // ❌ 报错:sayHello 未定义
    
    const sayHello = function() { return "Hello"; };

3. 避免冲突策略

  • 模块化:使用 ES6 模块或 IIFE 隔离作用域。

  • 对象封装

    const utils = {
      log: function() { /* ... */ }
    };
    const app = {
      log: function() { /* ... */ }
    };

二、函数的作用域与闭包

1. 作用域(Scope)

  • 词法作用域(Lexical Scope):函数在定义时确定作用域,而非执行时。

  • 块级作用域(Block Scope)let/const 声明的变量在 {} 内有效。

示例

function outer() {
  const outerVar = "outer";
  function inner() {
    console.log(outerVar); // 访问外部作用域变量
  }
  inner();
}
outer(); // 输出 "outer"
  • 在能够访问到的情况下先局部,局部没有再找全局。 

2. 闭包(Closure)

闭包是函数与其词法环境的组合,允许函数访问定义时的作用域变量,即使外部函数已执行完毕。

经典示例

function createCounter() {
  let count = 0;
  return function() {
    return ++count;
  };
}

const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2

实际应用

  • 封装私有变量。

  • 实现函数工厂(如生成不同配置的函数)。

  • 处理异步回调(保留上下文)。


三、高阶函数与函数式编程

1. 高阶函数

接受函数作为参数或返回函数的函数。

示例

// 接受函数作为参数(如数组方法)
const numbers = [1, 2, 3];
const doubled = numbers.map(x => x * 2); // [2, 4, 6]

// 返回函数
function createMultiplier(factor) {
  return function(x) {
    return x * factor;
  };
}
const triple = createMultiplier(3);
console.log(triple(5)); // 15

2. 纯函数

  • 输入相同则输出相同。

  • 无副作用(不修改外部状态)。

示例

// 纯函数
function pureAdd(a, b) {
  return a + b;
}

// 非纯函数(修改外部变量)
let total = 0;
function impureAdd(x) {
  total += x;
}

四、this 绑定与箭头函数

1. this 的指向规则

  • 默认绑定:非严格模式下指向全局对象(浏览器中为 window),严格模式为 undefined

  • 隐式绑定:函数作为对象方法调用时,this 指向对象。

  • 显式绑定:通过 call()apply()bind() 指定 this

  • new 绑定:构造函数中 this 指向新实例。

示例

const obj = {
  value: 42,
  getValue: function() {
    return this.value;
  }
};
console.log(obj.getValue()); // 42(隐式绑定)

const unboundGet = obj.getValue;
console.log(unboundGet()); // undefined(默认绑定)

2. 箭头函数的 this

箭头函数没有自己的 this,继承外层作用域的 this

对比示例

const obj = {
  value: 10,
  traditional: function() {
    setTimeout(function() {
      console.log(this.value); // undefined(默认绑定到全局)
    }, 100);
  },
  arrow: function() {
    setTimeout(() => {
      console.log(this.value); // 10(继承外层 this)
    }, 100);
  }
};
obj.traditional(); // undefined
obj.arrow();       // 10

五、异步函数与生成器

1. 回调函数与异步模式

传统异步操作依赖回调函数,但易导致“回调地狱”(Callback Hell)。

示例

fs.readFile('file1.txt', (err, data1) => {
  if (err) throw err;
  fs.readFile('file2.txt', (err, data2) => {
    if (err) throw err;
    console.log(data1 + data2);
  });
});

2. Promise 与 async/await

ES6+ 引入 Promise 和 async/await 简化异步代码。

示例

// Promise 链
fetchData()
  .then(data => processData(data))
  .catch(err => handleError(err));

// async/await
async function fetchAndProcess() {
  try {
    const data = await fetchData();
    const result = await processData(data);
    return result;
  } catch (err) {
    handleError(err);
  }
}

3. 生成器函数(Generator)

通过 function* 定义,可暂停和恢复执行,用于复杂异步流程控制。

示例

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

const gen = idGenerator();
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2

六、函数的高级技巧

1. 柯里化(Currying)

将多参数函数转换为单参数函数链式调用。

示例

function curry(fn) {
  return function curried(...args) {
    if (args.length >= fn.length) {
      return fn.apply(this, args);
    } else {
      return (...args2) => curried(...args, ...args2);
    }
  };
}

const curriedSum = curry((a, b, c) => a + b + c);
console.log(curriedSum(1)(2)(3)); // 6

2. 防抖(Debounce)与节流(Throttle)

优化高频事件(如滚动、输入)的性能。

防抖示例

function debounce(fn, delay) {
  let timer;
  return function(...args) {
    clearTimeout(timer);
    timer = setTimeout(() => fn.apply(this, args), delay);
  };
}

const debouncedSearch = debounce(searchAPI, 300);
input.addEventListener('input', debouncedSearch);

七、总结

  1. 优先使用箭头函数
    除非需要动态 this(如对象方法),否则箭头函数更简洁安全。

  2. 避免过度嵌套
    使用 async/await 或 Promise 链替代回调地狱。

  3. 合理使用闭包
    注意内存泄漏(如无用的变量引用未被释放)。

  4. 函数单一职责
    一个函数只做一件事,提高可测试性和可维护性。


相关文章:

  • 向量数据库介绍及应用
  • 影响HTTP网络请求的因素
  • LeetCode算法题(Go语言实现)_20
  • IPv6 网络访问异常 | 时好时坏 / 部分访问正常
  • STM32H743学习记录
  • SpringBoot (二) 日志系统
  • Python+拉普拉斯变换求解微分方程
  • 如何使用stable diffusion 3获得最佳效果
  • Zynq + FreeRTOS 笔试题1
  • STC89C52单片机学习——第37节: [17-1] 红外遥控(外部中断)
  • 详解list容器
  • socket演示程序2
  • xshell可以ssh连接,但vscode不行
  • 多路IO复用-----epoll和poll和select的区别
  • Windows系统本地部署DeepSeek详细教程
  • Ubuntu修改用户名
  • 朴素贝叶斯
  • AI人工智能-Python基础与程序流程控制
  • python正向先行断言讲解与举例
  • Javascript中的匿名函数
  • 洛可可设计/抖音seo源码搭建
  • 蓟县做网站/南宁百度推广代理商
  • 便宜的seo网站优化排名/长春百度推广公司
  • 徐州新沂网站建设/成品网站1688入口网页版
  • 网站建设公司好/外贸网站推广服务
  • dw做的网站如何上传/整站关键词排名优化