目录
定义:被定义的作用域外被调用时,仍可访问定义时的作用域内的变量
不再使用/为空的引用未被移除:闭包/DOM移除,子节点引用没移除
私有变量/方法:封装在函数内部,避免全局污染,保护变量不被外部访问和修改
闭包(closure)是一个函数以及其捆绑的周边环境状态(lexical environment,词法环境)的引用的组合
一个函数能够记住并访问其词法作用域,即使该函数在其词法作用域之外执行。
即一个函数在被定义的作用域外被调用时,仍然可以访问在它定义时的作用域内的变量。
词法(lexical)作用域:
根据源代码中声明变量的位置来确定该变量在何处可用。
js作用域生命周期在于内部脚本是否全部执行完毕才会销毁,并且不会带到父级作用域;
- function createCounter() {
- let counter = 0
- const myFunction = function() {
- counter = counter + 1
- return counter
- }
- return myFunction
- }
- const increment = createCounter()
- const c1 = increment()
- const c2 = increment()
- const c3 = increment()
- console.log('example increment', c1, c2, c3)//1 2 3
内存泄漏:引用->无法被垃圾回收->内存浪费->慢->崩溃
不再使用/为空的引用未被移除:闭包/DOM移除,子节点引用没移除
性能损耗:作用域链的查找,性能损耗
JavaScript 没有私有变量的原生支持
- var Counter = (function () {
- var privateCounter = 0;
- function changeBy(val) {
- privateCounter += val;
- }
- return {
- increment: function () {
- changeBy(1);
- },
- decrement: function () {
- changeBy(-1);
- },
- value: function () {
- return privateCounter;
- },
- };
- })();
-
- console.log(Counter.value()); /* logs 0 */
- Counter.increment();
- Counter.increment();
- console.log(Counter.value()); /* logs 2 */
- Counter.decrement();
- console.log(Counter.value()); /* logs 1 */
- function createPubSub() {
- // 存储事件及其对应的订阅者
- const subscribers = {};
-
- // 订阅事件
- function subscribe(event, callback) {
- // 如果事件不存在,则创建一个新的空数组
- if (!subscribers[event]) {
- subscribers[event] = [];
- }
- // 将回调函数添加到订阅者数组中
- subscribers[event].push(callback);
- }
-
- // 发布事件
- function publish(event, data) {
- // 如果事件不存在,则直接返回
- if (!subscribers[event]) {
- return;
- }
- // 遍历订阅者数组,调用每个订阅者的回调函数
- subscribers[event].forEach((callback) => {
- callback(data);
- });
- }
-
- // 返回订阅和发布函数
- return {
- subscribe,
- publish,
- };
- }
-
- // 使用示例
- const pubSub = createPubSub();
-
- // 订阅事件
- pubSub.subscribe("event1", (data) => {
- console.log("订阅者1收到事件1的数据:", data);
- });
-
- pubSub.subscribe("event2", (data) => {
- console.log("订阅者2收到事件2的数据:", data);
- });
-
- // 发布事件
- pubSub.publish("event1", "Hello");
- // 输出: 订阅者1收到事件1的数据: Hello
-
- pubSub.publish("event2", "World");
- // 输出: 订阅者2收到事件2的数据: World
- function calculator() {
- let result = 0;
-
- function add(num) {
- result += num;
- return this;
- }
-
- function subtract(num) {
- result -= num;
- return this;
- }
-
- function multiply(num) {
- result *= num;
- return this;
- }
-
- function divide(num) {
- result /= num;
- return this;
- }
-
- function getResult() {
- return result;
- }
-
- function clear() {
- result = 0;
- return this;
- }
-
- return {
- add,
- subtract,
- multiply,
- divide,
- getResult,
- clear,
- };
- }
- const calc = calculator();
- const result = calc.add(5).subtract(2).divide(3).multiply(6).getResult();
- console.log(result); // 输出:6
函数组件的闭包特性来存储和更新状态
- class MyComponent extends React.Component {
- handleClick = () => {
- console.log(this); // this指向MyComponent组件本身
- }
-
- render() {
- return (
- <button onClick={this.handleClick}>按钮button>
- );
- }
- }
-
- class MyComponent extends React.Component {
- handleClick() {
- console.log(this); // this指向window对象或undefined(视情况而定)
- }
-
- render() {
- return (
- <button onClick={() => this.handleClick()}>按钮button>
- );
- }
- }
-