[JS]01.函数底层处理机制

214 阅读9分钟

大纲

1. 堆栈内存和闭包作用域

  • 堆栈内存及底层处理机制
  • 玩转作用域和闭包机制
  • 高阶编程技巧:柯里化函数、惰性函数、模块化开发、组合函数等
  • jQuery & Lodash 源码解读

2. 面向对象程序设计

  • 构造函数 & 原型 & 原型链 & Function VS Object
  • 全面剖析 this 的五种情景及应用实战
  • 全面解析js中的4种 数据类型检测 及方法封装
  • call & apply & bind & instanceof & new 源码剖析
  • jQuery & Lodash 源码解读

3. 深入浏览器的底层运行机制

  • DOM树 & CSSDOM树 & RENDER树 & LAYOUT & 分层 & PAINTING
  • CRP关键渲染路径和前端性能优化
  • EventLoop & EventQueue & 微任务 & 宏任务
  • 移动端白屏优化方案之骨架屏技术Skeleton

4. 事件 & 设计模式 & 插件组件封装

  • 事件池机制 & 事件传播 & 事件代理
  • 设计模式:观察者、发布订阅、单例、工厂、代理、装饰...
  • 开源级插件组件封装
  • jQuery & Lodash 源码解读

5. ES6核心知识和源码分析

  • Promise和PromiseA+规范源码
  • async & await 源码实现
  • generator & iterator & Set & Map & WeakSet & WeakMap
  • 模块化:AMD、CMD、CommonJS、ES6Module
  • ES新特性解析

6. AJAX/HTTP前后端数据交互和网络通信

  • HTTP & HTTPS & HTTP2.0 & DNS & TCP
  • 基于HTTP网络层的前端性能优化汇总分析
  • ajax & fetch & axios & 数据传输格式
  • axios源码分析 & 二次配置封装
  • 基于Promise封装自己的axios和fetch库
  • N种跨域方案及底层原理剖析

第一讲:JS中的堆栈内存及函数底层处理机制

1. js中的数据类型

  • 一、基本数据类型(值类型、原始类型)
    • number
      • NaN
      • Infinity
    • string
    • boolean
    • null
    • undefined
    • symbol 唯一值
      • static Symbol
      • Symbol.prototype
    • bigint
  • 二、引用数据类型
    • object
      • 普通对象
      • 数组对象
      • 正则对象
      • 日期对象
      • JSON对象
      • Set
      • Map
    • function
      • 普通函数
      • 构造函数
      • 箭头函数
      • 生成器函数
typeof 10 => "number"
typeof NaN => "number"
typeof "" => "string"
typeof nul => "undefined" 暂时性死区 输入错误nul
typeof null => "object"      // 000000 三零开头 object
typeof undefined => "undefined"
typeof Symbol() => "symbol"
typeof {} => "object"
typeof [] => "object"   // => 都是object 不能细分对象
typeof /^$/ => "object"
typeof function(){} => "function"

/* 无穷大 */
Infinity === Infinity => true
/* 不是一个数字,都有可能,不能相等 */
NaN === NaN => false
/*
** 1. 用 isNaN()返回布尔值,检测是否有效数字
** 2. Object.is(NaN, NaN),检测两个值是否相等 => true
*/

1.1. typeof的原理

  • 所有的数据类型值在计算机中存储的都是二进制
  • null的二进制值是 000000
  • 只要是对象,都是以 000 开始的
  • typeof不能细分对象具体种类(数组,正则等)
  • typeof检测时,是按照计算机存储的二进制值来检测的
  • function不是以 000 开始的

1.2 Symbol() 唯一值

  • 每运行一次都是唯一值,不是构造函数,不能被new
console.log(Symbol())  ==>   Symbol()
//  CC是标记
console.log(Symbol('CC'))  ==>   Symbol('CC')

// Symbol不能被new
console.log(new Symbol()) 
// Uncaught TypeError: Symbol is not a constructor

console.log(Symbol('AA') === Symbol('AA'))
// false 每次创建都是唯一值

let symb = Symbol('BB')
console.log(symb === symb) => true
  • 用途:给对象设置唯一属性,在vuex/redux中做行为派发时,统一管理派发的行为标识,标识的值可以是唯一值

  • Symbol核心方法 dir(Symbol) 展开

Symbol.hasInstance
Symbol.toPrimitive
Symbol.toStringTag
Symbol.iterator
Symbol.isConcatSpreadable
Symbol.match

1.3 bigint 超大数字

  • 最大安全数字:Number.MAX_SAFE_INTEGER
  • 最小安全数字:Number.MIN_SAFE_INTEGER
  • 2的60次方:Math.pow(2,60)
  • 超过安全范围后面加n,数字后加n就是bigint
  • typeof 9007199254740992000n => "bigint"
    • 9007199254740992000n + 1n 可以计算

2. 栈内存Stack & 堆内存 Heap

  • 数据类型的区别:堆内存和栈内存

  • 基本概念

    • declare->声明变量 & defined->关联变量和值
    • ECStack: Execution Context Stack 执行环境栈
    • EC: Execution Context 执行上下文
    • VO: Varibale Object 变量对象
    • GO: Global Object 全局对象
      • 浏览器加载页面时,默认形成全局对象window,window指向全局对象,存放浏览器供JS调用的属性和方法,setTimeout等

2.1 执行环境栈(ECStack)

  • 浏览器之所以能够运行JS代码:它会在计算机的内存中分配出一块区域,就是栈内存
  • 作用:用来供代码执行 & 存储基本数据类型值
  • 这个区域就是栈内存,ECStack,Execution Context Stack 执行环境栈

2.2 执行上下文(EC)

  • 为了在执行环境栈中区分是哪个区域(全局EC(G)的代码还是函数的代码)下的代码执行,会产生一个叫执行上下文的。
  • 这个区域就是全局的执行上下文,Execution Context(global)是全局执行上下文。
  • 函数执行会形成全新的私有的上下文,不是全局上下文
  • EC执行时,会进入ECStack,进栈执行
  • 全局执行上下文中EC(G)下有window对象,指向GO

2.3 变量对象(Varibale Object)

  • EC全局执行上下文中,用VO(G)全局变量对象,存储当前上下文声明的变量

2.4 声明变量的解析过程

  • 执行 var 变量 = 值 分三步

    • 第一步:先创建值
      • 基本类型值:直接存储在栈(stack)内存中
      • 引用类型值(对象和函数):开辟一个单独的内存空间,堆(Heap)
    • 第二步:声明变量 declare
      • 存放到当前上下文(EC)的变量对象(VO)中
      • 引用类型关联,即存储的是内存地址
    • 第三步:关联声明和值 defined,此操作叫定义
  • 只声明不定义,只执行了第二步,给默认值undefined

  • 基本类型直接存在栈内存中,直接按值操作,引用数据类型是开辟单独的堆内存存储信息的,操作的是引用地址

// 从右向左

// 情况1
var a = 12;
    b = 13;
// 解析过程: var a = 12; var b = 13;

// 情况2
var a = b = 13;
// 解析过程:从右向左,b = 13, var a = b;

// 情况3 成员访问优先级仅次于括号
a.x = b = 13;
b = a.x = 13;
// a.x是成员访问 在js运算优先级中,19,仅次于括号()的20
// 不管写在前面还是后边,先计算a.x = 13,再计算a.x=b

// 例子
var a = {n: 1}
var b = a;
a.x = a = {n: 2}
console.log(a.x)
console.log(b)
// a和b初始都指向{n:1}
// 先计算a.x, a.x指向{n:2}, 再计算a={n:2}
// a指向了 {n:2}
// b指向的对象被a.x变成 {n:1, x:{n:2}}
// a指向{n:2},a.x为undefined,b为{n:1, x:{n:2}}

2.5 函数的底层处理机制

var x = [12, 23];
function fn(y) {
    y[0] = 100;
    y = [100];
    y[1] = 200;
    console.log(y);
}
fn(x);
console.log(x);
// [100, 200], [100, 23]

1. JS中的上下文

  • 全局上下文EC(G)
  • 函数执行会形成一个全新的私有上下文
  • ES6中块级私有上下文

2. 创建一个函数和创建一个变量类似

  • 都是声明一个变量存储值
  • 函数的函数名也算是变量 fn
    • function fn(y) {...} 类似于 var fn = function(y) {...}
    • 函数表达式:把一个函数作为值赋值给一个变量或者其他事物

3. 创建一个函数也需要开辟一个堆内存

  • 对象的堆内存中,存储的是对象的键值对
  • 函数的堆内存中,存储的是它的代码,而且是以字符串的形式存储
    • 创建函数的时候就声明了函数的作用域
    • scope值是当前创建函数时候所处的上下文

4. 代码的执行过程

  • 执行环境栈ECStack开辟空间
  • 全局上下文EC(G)中声明x以及fn,进栈,并开辟堆内存,存放数组以及函数
  • 数组堆内存:[12, 23]
  • 函数堆内存
    • 代码字符串
    • 并存储scope,EC(G)在哪个上下文中创建的,作用域是谁
    • 形参y
  • 函数执行,函数堆内存fn(y)形成一个全新的私有上下文AO(fn),进栈
    • 形参y的值,赋值
    • 作用域链,<EC(fn), EC(G)>,函数自己作用域和上级外部全局作用域
    • 代码字符串执行

5. 相关概念

  • 私有变量:私有上下文中声明的变量
    • 形参是私有变量
    • 代码执行时声明的变量 var/let/const/function
  • 全局变量:全局上下文中声明的变量
    • 全局变量可以通过参数传递成私有变量
  • 作用域链查找机制
    • 私有上下文中代码,通过作用域链去查找变量,如果没有,逐级向上

6. 函数执行的步骤

  • 形成一个私有的上下文,Active Object私有变量,存储当前上下文中声明的变量,然后进栈执行
  • 代码执行之前
    • 初始化作用域链,scope-chain
      • 结构:<(当前自己的私有上下文,函数的作用域), (上级上下文)>
    • 初始化this,arguments
    • 形参赋值
    • 变量提升
  • 代码执行
  • 出栈释放

3.浏览器垃圾回收机制

  • GC:浏览器的垃圾回收机制(内存释放机制)

3.1 栈内存释放

  • 加载页面,会形成一个全局上下文,只有页面关闭的时候,全局上下文才会被释放。(全局变量,关闭才释放)
x = null
fn = null // 手动取消占用,变量堆内存被释放
// 代码执行完成就会出栈释放,上下文释放,占用释放
  • 函数执行时会形成一个私有的上下文,进栈执行,当函数中代码执行完成,大部分情况下,形成的上下文都会被出栈释放,以此优化栈内存大小。

3.2 堆内存释放

  • 方案一:chrome,查找引用
    • 浏览器会在指定或者空闲时间内,查看所有的堆内存,把没有被占用的堆内存释放掉,被占用的不能释放。
  • 方案二:IE,引用计数
    • 创建了堆内存,如果被占用一次,则浏览器计数+1,取消占用,计数-1,当记录的数字为0时,则内存释放。
    • 某些情况会导致计数混乱,会导致内存泄露现象,该释放的内存没有释放。

3.3 闭包 不被销毁的局部私有变量

  • 函数执行,会形成私有上下文EC(fn)
  • 函数执行之前要初始化作用域链(连接上下文) ...
  • 当前上下文创建的0X001,console函数,被当前上下文以外的全局上下文f占用,当前上下文不能释放

image.png

·