javascript技巧

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript技巧 > js函数和对象

JS函数和对象全解析

作者:虚拟系别

文章主要介绍了JavaScript中的垃圾回收机制、闭包、函数参数以及ES6箭头函数,ES6箭头函数简化了函数写法,并重塑了this的指向规则,本文结合实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧

一、垃圾回收机制

JS作为高级语言,无需开发者手动分配和释放内存,核心依赖“垃圾回收机制(GC)”自动清理不再使用的内存空间,避免内存泄漏。

1. 核心原则

垃圾回收的核心是“识别并回收不可达对象”——当一个对象无法通过任何引用链访问到时,就会被标记为“垃圾”,等待GC清理。

2. 两种常见回收算法

标记-清除算法(主流):这是现代浏览器最常用的算法,分两步执行:

引用计数算法(淘汰):通过统计对象被引用的次数判断是否回收——引用次数为0则标记为垃圾。但存在致命缺陷:循环引用时(A引用B,B引用A,且两者均无其他引用),引用次数永远不为0,导致内存泄漏。

3. 实用注意事项

虽然GC自动执行,但不良代码仍可能导致内存泄漏,需注意:

二、闭包

闭包是JS的核心特性,也是面试高频考点,理解它能轻松实现模块化、状态保存等功能。

1. 定义与本质

当一个函数嵌套另一个函数,且内层函数引用了外层函数的变量/参数,同时内层函数被外部访问时,就形成了闭包。本质是“内层函数携带了外层函数的作用域上下文”,让外层变量在函数执行结束后仍不被回收。

2. 经典案例

实现计数器(保存状态,避免全局污染)

function createCounter() {
  let count = 0; // 外层函数变量,被内层引用
  return function() {
    count++; // 内层函数访问外层变量
    return count;
  };
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3

解析:createCounter执行后,按常理count会被GC回收,但因内层函数被counter引用,闭包保留了count的引用,使其能持续累加,且count无法被外部直接修改,实现了“私有变量”的效果。

3. 应用场景与坑点

常用场景:

注意坑点:

闭包会延长外层变量的生命周期,过度使用会增加内存负担,甚至导致内存泄漏。建议:仅在需要保存状态/封装变量时使用,使用完毕后可通过“清空引用”(如counter = null)释放内存。

三、函数参数

JS函数参数看似简单,实则有诸多进阶技巧,能大幅提升代码灵活性,覆盖默认值、剩余参数、解构传参等场景。

1. 默认参数(ES6+)

ES6前需通过逻辑判断设置默认值(如param = param || 'default'),但存在缺陷(若参数为0、false等假值,会被误判为无参)。ES6新增默认参数语法,简洁且精准:

// 基础用法
function greet(name = 'Guest', age = 18) {
  console.log(`Hello ${name}, you are ${age} years old`);
}
greet(); // Hello Guest, you are 18 years old
greet('Tom'); // Hello Tom, you are 18 years old
// 注意:默认参数需放在参数列表末尾
function fn(a, b = 2) {} // 合法
function fn(b = 2, a) {} // 不推荐,易混淆

2. 剩余参数(…rest)

当函数参数数量不确定时,用剩余参数(…+变量名)接收多余参数,返回一个数组(区别于arguments的类数组),便于遍历操作:

// 求和函数(支持任意数量参数)
function sum(...nums) {
  return nums.reduce((total, num) => total + num, 0);
}
console.log(sum(1,2,3)); // 6
console.log(sum(4,5,6,7)); // 22
// 剩余参数与普通参数结合(剩余参数必须在最后)
function fn(a, b, ...rest) {
  console.log(a, b); // 1 2
  console.log(rest); // [3,4,5]
}

3. 参数解构(ES6+)

当参数为对象/数组时,可通过解构直接提取属性/元素,简化代码:

// 对象解构传参
function getUserInfo({ name, age, gender = 'male' }) {
  console.log(`姓名:${name},年龄:${age},性别:${gender}`);
}
getUserInfo({ name: 'Tom', age: 20 }); // 姓名:Tom,年龄:20,性别:male
// 数组解构传参
function getSum([a, b, c]) {
  return a + b + c;
}
console.log(getSum([1,2,3])); // 6

四、ES6箭头函数:简洁与this的重塑

箭头函数是ES6最常用的语法糖,不仅简化函数写法,更重塑了this的指向规则,解决了传统函数this指向混乱的问题。

1. 基础语法

// 无参数,单语句
const fn1 = () => console.log('Hello');
// 单参数,单语句(可省略括号)
const fn2 = num => num * 2;
// 多参数,多语句(需加括号和大括号,return不可省略)
const fn3 = (a, b) => {
  const total = a + b;
  return total;
};
// 返回对象(需加小括号,避免大括号被解析为代码块)
const fn4 = () => ({ name: 'Tom', age: 20 });

2. 核心特性:this指向

传统函数(普通函数、构造函数)的this指向“调用者”,而箭头函数没有自己的this,其this继承自外层执行上下文的this,且一旦绑定无法修改(call、apply、bind也无效)。

// 传统函数this指向问题
const obj = {
  name: 'Tom',
  sayHi: function() {
    setTimeout(function() {
      console.log(this.name); // undefined(this指向window)
    }, 1000);
  }
};
// 箭头函数解决this问题
const obj2 = {
  name: 'Tom',
  sayHi: function() {
    setTimeout(() => {
      console.log(this.name); // Tom(this继承自sayHi的this,即obj2)
    }, 1000);
  }
};

3. 适用与不适用场景

适用场景:

不适用场景:

到此这篇关于JS函数和对象全解析的文章就介绍到这了,更多相关js函数和对象内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文