金色小芝麻

vuePress-theme-reco 金色小芝麻    2021 - 2023
金色小芝麻 金色小芝麻

Choose mode

  • dark
  • auto
  • light
主页
分类
  • JavaScript
  • BUG复盘
  • SVG笔记
  • TypeScript
  • 个人总结
  • CSS笔记
  • 开发工具
  • 前端入门
  • Vue2.0
  • 性能优化
  • 架构学习
  • 每日一题
标签
时间轴
社交
  • 掘金 (opens new window)
author-avatar

金色小芝麻

83

文章

27

标签

主页
分类
  • JavaScript
  • BUG复盘
  • SVG笔记
  • TypeScript
  • 个人总结
  • CSS笔记
  • 开发工具
  • 前端入门
  • Vue2.0
  • 性能优化
  • 架构学习
  • 每日一题
标签
时间轴
社交
  • 掘金 (opens new window)
  • 前端入门

    • 博客搭建过程及相关配置
    • 数组中的16种常用方法
    • JS中的数据类型简析——基本数据类型值
    • JS中的数据类型object基础
    • JS中三种常见的判断
    • 数据类型之间的区别(堆内存Heap VS 栈内存Stack)
    • JS基础练习题及解析
    • 开关灯的小案例
    • JS中数据类型检测方法——typeof
    • 条件判断几个小练习
    • JS循环——for循环
    • 自定义属性实现选项卡小案例
    • 字符串中的12种常用方法
    • DOM操作的简单原理
    • JS实现隔行变色鼠标跟随小案例
    • JS中function的基础知识
    • JS中数组去重的三种方法
    • JS中时间格式化的三种方法
    • JS中URL参数处理的三种方法
    • JS小案例——获取随机验证码
    • DOM操作之——获取DOM标签的9种方式
    • DOM操作之——DOM节点类型及属性
    • DOM操作之——元素的增删改、样式修改、插入内容
    • JS中THIS相关问题梳理
    • JS中的变量提升机制
    • 在全局:私有上下文中:带VAR和不带VAR的区别
    • 作用域和作用域链查找机制
    • JS中堆栈内存的释放问题
    • JS中的闭包机制
    • ES3和ES6定义变量的区别
    • JS中的单例和工厂设计模式
    • JS中的面向对象OOP理论基础
    • 构造函数创建自定义类
    • JS中的原型和原型链
    • Math中常用的9种方法
    • 从一道阿里经典面试题剖析函数三种角色
    • 重写内置call
    • 重写一个内置new
    • 浏览器渲染页面的主体流程
    • 减少DOM的回流和重绘
    • JS中的多种继承方式
    • JS中数据类型检测四种方式的优缺点
    • JS中的正则表达式&&全面梳理
    • 非严格模式 🆚 严格模式的区别
    • 数组方法reduce、filter、flat
    • 获取数组中最大值/最小值的三种基础方法
    • 轮播图——渐隐渐显版
    • 深克隆 VS 浅克隆|深比较 VS 浅比较|回调函数
    • 轮播图——左右切换版
    • 事件及事件绑定、事件对象及事件传播
    • 从在地址栏输入网址到看到页面的过程&&AJAX基础
    • 想自学JS吗?想提升JS底层原理吗?76张脑图带你彻底搞懂原生JS
    • 面试手写API系列
    • 30张脑图带你从零开始学VUE
    • JS中的盒子模型
    • 初识JS-基础中的基础
    • 前端发展简史
    • JS中的三大类输出方式

JS中的闭包机制

vuePress-theme-reco 金色小芝麻    2021 - 2023

JS中的闭包机制

金色小芝麻 2020-05-21

# 思维导图

# 一、什么是闭包机制

函数执行形成的私有上下文,即能保护里面的私有变量不受外界干扰,也能在当前上下文中保存一些信息(前提:形成的上下文不销毁),上下文中的这种保存和保护机制,就是闭包机制

# 二、闭包的两大作用

# 1、保护作用

在这个上下文中会有一些私有的变量AO(XX),这些私有的变量和外界的变量不会冲突(互不影响)

# 2、保存作用

某些情况下,上下文中的某些内容被外界占用后,当前上下文并不会出栈销毁,这样就会把上下文中的一些信息储存起来

# 三、闭包的应用

# 1.利用闭包的保护作用

  • -1).团队协作开发中;
    • A/B共同开发一个页面,最后要把代码合并在一起,为了防止全局变量的冲突污染,我们建议每个开发者,都把自己的代码放置到一个闭包中(自执行函数执行即可,这样就是私有的上下文)保护起来
// A的代码
(function anonymous() {
    /* 自执行函数执行,会形成一个私有的上下文,在这里声明+定义的变量或者函数都是私有的 */
    var x = 100,
        y = 200;

    function func() {
        // ...
    }
})();

// B的代码
~ function anonymous() {
    // console.log(anonymous); //=>函数本身 
    //=>匿名函数设置的函数名只能在函数里面应用,函数外面是无法访问的
    var x = 200,
        n = 0;

    function func() {
        // ...
    }

    function handled() {
        // ...
    }
}();
// console.log(anonymous); //=>Uncaught ReferenceError: anonymous is not defined 
  • -2).封装一个插件或者类库等;
    • 为了防止我们定义的变量和方法 和 用户定义的冲突,我们也是需要把所有写的代码放到一个闭包中,例如:jQuery...
/* JQUERY源码一瞥 */

// typeof window !== "undefined" ? window : this  浏览器端window是存在的,所以为window
(function (global, factory) {
	"use strict";
	// => global===window
	// => factory===function (window, noGlobal){...}
	factory(global);
})(window, function (window, noGlobal) {
	// JQUERY的源码
}); 
//=> 利用闭包的机制,把JQ源码当作自执行函数的形参传给函数,完成执行

# 2.利用闭包的保存作用

  • -1).在某些需求中,我们经常需要形成一个闭包,存储一些值(而且不能销毁),这样来供后面的程序运行使用(例如:惰性函数、柯理化函数、compose函数等JS高阶编程技巧中,就是基于闭包的保存机制实现的)

此时我们发现一个问题:每个人的代码都独立了,那我们每个人都会用到的公共方法,难道也要都单独写一遍?

有此需求,必然得有解决办法:

# 四、闭包内的值暴露给外面使用的两种方法

需求:我们需要把某一个闭包(私有上下文)中的值暴露到外面

# 1、基于window.xxx=xxx暴露到全局

这种办法虽然可以实现,但是也会存在冲突,如果我们每一个版块都需要暴露更多的方法,同时都基于这种方法暴露到全局对象GO上,也可能导致方法之间的冲突

(function anonymous() {
    function queryURLParams() {
        // ...
    }

    function sum() {
        // ...
    }

// 想暴露到外面使用,可以暴露到全局上(赋值给全局对象GO =>window)
    window.queryURLParams = queryURLParams;
    window.sum = sum;
})();
queryURLParams(); //=>window.queryURLParams() 

# 2、JS中的设计模式:单例设计模式

每一个版块暴露到全局下只有一个变量而已,所有需要供别人调取的方法都在对象中(这样暴露一个或者多个都无所谓)

  • 避免了全局变量的污染,也同时实现了不同闭包之间方法的公用性
var utils = (function anonymous() {
    // queryURLParams:获取URL地址参数信息
    function queryURLParams() {
        // ...
    }

    // sum:实现任意数求和
    function sum() {
        // ...
    }

    // 把需要供外面访问的变量和方法,赋值给一个对象,最后返回(外层基于VAR utils定义变量来接收即可)
    return {
        queryURLParams: queryURLParams,
        sum: sum
    }; //=>return AAAFFF000;
})();
// console.log(utils); //=>{queryURLParams:函数,sum:函数}
utils.queryURLParams();
utils.sum(); 
utils对象中包含了需要供别人调取使用的方法;此时我们把utils称之为“命名空间”,而对象就是一个空间,空间中包含了当前版块中的内容,或者是把当前版块中的内容按照命名空间进行了分组,每一个分组都是一个单独的个体

# 命名空间

  • 把每一个对象值 赋值给变量 =>可以理解为,给每一个对象的堆内存空间起了个变量名,所以此时可以把这个变量称为 “命名空间”
  • 当前对象中的键值对都是 命名空间 中私有的键值对

# 五、闭包的优缺点

# 1、优点

  • 上述我们一直说的保护和保存作用

# 2、缺点

  • 因为闭包会产生不销毁的上下文,这样导致栈/堆内存消耗过大,有时候也会导致内存泄漏等,影响页面的运行性能,所以在真实项目中,要合理应用闭包(不要滥用)
欢迎来到 金色小芝麻
看板娘