闭包治愈“全局变量恐惧症”,利用闭包实现JavaScript私有变量(二)

简介: 闭包治愈“全局变量恐惧症”,利用闭包实现JavaScript私有变量

闭包治愈“全局变量恐惧症”,利用闭包实现JavaScript私有变量(一)https://developer.aliyun.com/article/1426535


2. 事件绑定

在JavaScript中,事件处理程序通常需要访问元素的一些属性或者其他变量。由于事件处理程序通常作为全局函数定义,因此它无法访问事件处理程序函数之外的变量。但是通过使用闭包,可以在事件处理程序内部访问外部的变量。

function addClickHandler(el, fn) {
  el.addEventListener('click', function() {
    fn();
  });
}
const button = document.querySelector('#myButton');
const name = '张三';
addClickHandler(button, function() {
  alert(`你好, ${name}!`);
});

在这个例子中, addClickHandler 函数通过闭包,允许事件处理程序内部访问外部变量 name,而且这种方式不会导致全局变量的污染。

3. 循环变量绑定

在循环语句中,经常需要将循环变量绑定到按钮或者链接等元素中。使用循环变量绑定时,需要注意循环变量和事件处理程序之间的作用域问题。使用闭包,可以解决循环变量和事件处理程序之间的作用域问题。

function createHandler(i) {
  return function() {
    console.log(`按钮 ${i} 被点击了`);
  }
}
for(let i = 0; i < 5; i++) {
  const button = document.createElement('button');
  button.innerText = `按钮 ${i}`;
  button.addEventListener('click', createHandler(i));
  document.body.appendChild(button);
}

在这个例子中, createHandler 函数使用闭包来创建一个可以访问循环变量的事件处理程序。而不使用闭包的话,事件处理程序将只能访问循环结束时循环变量的值。

IV. 闭包的优缺点

闭包的优点

数据的封装

闭包在数据封装上有以下优点:

1. 私有化变量和方法

闭包可以将变量和方法封装在一个函数作用域内,使得这些变量和方法只能在函数内部被访问,从而实现数据的封装。外部作用域无法直接访问闭包内部的变量和方法,只能通过相关的公有方法来访问或者修改数据。

function Counter() {
  let count = 0;
  return {
    increment: function() {
      count++;
    },
    decrement: function() {
      count--;
    },
    getCount: function() {
      return count;
    }
  };
}
const counter = Counter();
counter.increment(); // count+1
console.log(counter.getCount()); // 输出 1

在这个例子中, count 变量和三个方法都被封装在 Counter 函数内部,只能通过 Counter 函数返回的方法来访问或者修改 count 变量的值。

2. 避免全局变量的污染

使用闭包可以避免全局变量的污染。在函数作用域内部定义变量和方法时,它们不会影响全局作用域中已经存在的同名变量和方法,从而避免了命名冲突等问题。

let count = 0;
function Counter() {
  count = 10;
  return {
    increment: function() {
      count++;
    },
    decrement: function() {
      count--;
    },
    getCount: function() {
      return count;
    }
  };
}
const counter = Counter();
counter.increment(); // count+1
console.log(counter.getCount()); // 输出 11
console.log(count); // 输出 10

在这个例子中, count 变量已经被定义在全局作用域中,但是通过在 Counter 函数内部重新定义一个同名的 count 变量,实现了局部变量的封装,避免了对全局 count 变量的修改。

因此,使用闭包可以实现对数据的封装,并且避免全局变量的污染,有助于提高代码的可读性和可维护性。

可以实现高阶函数

闭包可以实现高阶函数,并且在高阶函数中发挥重要作用,具有以下优点:

1. 强大的表现力

闭包可以将函数作为参数和返回值传递,实现更加灵活的函数组合和转换,从而快速构建复杂的功能模块。这种能力称为函数式编程中的柯里化(currying)和组合(composition)。

function add(x) {
  return function(y) {
    return x + y;
  };
}
function multiply(x) {
  return function(y) {
    return x * y;
  };
}
const add5 = add(5);
const multiply2 = multiply(2);
const result = add5(2); // 5 + 2 = 7
const result2 = multiply2(result); // 7 * 2 = 14
console.log(result2); // 输出 14

在这个例子中,addmultiply 函数都是返回一个闭包,而且这两个闭包接受一个参数并进行计算。通过组合这两个闭包,可以实现一个更加复杂的计算过程,从而实现高阶函数的功能。

2. 支持延迟求值

闭包支持延迟求值,也就是说,在某些情况下,可以将函数的执行延迟到需要的时候再执行,从而避免不必要的计算和内存占用。这种方法称为惰性求值(lazy evaluation)。

function createSquares(max) {
  const squares = [];
  function getSquare(i) {
    return function() {
      return i * i;
    };
  }
  for(let i = 0; i <= max; i++) {
    squares.push(getSquare(i));
  }
  return squares;
}
const squares = createSquares(10000);
console.log(squares[0]()); // 输出 0
console.log(squares[1]()); // 输出 1
console.log(squares[2]()); // 输出 4
// 将一次性计算所有的平方数改成延迟计算
const squares2 = createSquares(10000);
console.log(squares2[0]()); // 输出 0
console.log(squares2[1]()); // 输出 1

在这个示例中,createSquares 函数返回一个闭包数组,这些闭包可以在需要时延迟计算实际的值,解决了在一次性计算所有平方数时可能面临的性能问题,从而提高了运行效率。对于大数据量的计算,使用惰性求值可以节省大量的内存和计算资源。

因此,利用闭包可以创建高阶函数,实现更加灵活的函数组合和转换,还可以支持惰性求值,提高代码性能和运行效率。


闭包治愈“全局变量恐惧症”,利用闭包实现JavaScript私有变量(三)https://developer.aliyun.com/article/1426537

相关文章
|
27天前
|
JavaScript 前端开发 安全
详细讲解JavaScript中的闭包问题附代码演示
闭包是JavaScript中一关键概念,它允许内部函数访问外部函数的作用域,从而实现变量的封装与持久化。本文通过示例解释了闭包的工作原理及其优势,如数据隐藏和私有变量的实现;同时也指出了闭包可能导致的内存占用问题,强调合理使用的重要性。
20 1
|
27天前
|
JavaScript 前端开发 Java
JavaScript中的闭包概念讲解
闭包是指函数内部嵌套另一个函数,并且内部函数引用了外部函数的数据(如变量或函数)。这样的内部函数被称为闭包。以示例代码为例,`fn1` 中有两个闭包函数 `fn2` 和 `fn3`,它们都可以访问并修改 `fn1` 中的变量 `a`。
11 1
|
7天前
|
自然语言处理 JavaScript 前端开发
|
15天前
|
自然语言处理 前端开发 JavaScript
前端进阶必读:JS闭包深度解析,掌握这一特性,你的代码将焕然一新!
【8月更文挑战第23天】闭包是JavaScript的一项高级功能,让函数能够访问和操作外部函数作用域中的变量。本文深入解析闭包概念、组成及应用场景。闭包由函数及其词法环境构成,通过在一个函数内定义另一个函数来创建。它有助于封装私有变量、维持状态和动态生成函数。然而,不当使用闭包可能导致内存泄漏或性能问题。掌握闭包对于实现模块化代码和成为优秀前端开发者至关重要。
27 0
|
23天前
|
JavaScript 前端开发
js中this是指向的哪个全局变量,改变this指向的方法有什么?
js中this是指向的哪个全局变量,改变this指向的方法有什么?
13 0
|
26天前
|
JavaScript 前端开发 安全
JS 闭包(1)
JS 闭包(1)
23 0
|
26天前
|
JavaScript Java
JS 闭包
JS 闭包
21 0
|
26天前
|
存储 JavaScript 前端开发
JavaScript——对闭包的看法,为什么要用闭包?说一下闭包原理以及应用场景
JavaScript——对闭包的看法,为什么要用闭包?说一下闭包原理以及应用场景
27 0
|
4月前
|
设计模式 JavaScript 前端开发
js开发:请解释闭包(closure)是什么,以及它的用途。
闭包是JavaScript中的关键特性,允许函数访问并操作外部作用域的变量,常用于实现私有变量、模块化和高阶函数。私有变量示例展示了如何创建无法外部访问的计数器;模块化示例演示了封装私有变量和函数,防止全局污染;高阶函数示例则说明了如何使用闭包创建能接收或返回函数的函数。
41 2
|
4月前
|
自然语言处理 JavaScript 前端开发
JavaScript基础知识:什么是闭包(Closure)?
JavaScript基础知识:什么是闭包(Closure)?
45 0