Skip to content

webkit底层渲染机制

  • 浏览器中打开页面,会在计算机中分配出两块内存,栈内存和叫堆内层

  • 栈内存叫做 ECStack(Execution Context Stack),执行上下文栈,是用来提供代码执行的环 境,让代码自上而下执行,同时存储声明的变量和原始值类型的值。 堆内存用来存储引用类型的值,有一个 16 进制的地址值,存储键值对,对于函数来说除了存储 键值对,如 { name: 函数名, length: 函数定义时的形参个数 } 等信息以外,还要存代码字符 串,scope 作用域,最后把地址放入栈中,和变量关联起来。同时因为浏览器提供了内置的一些 属性和方法,浏览器就会在开辟的堆内存中,默认分配一块空间,用来存放那些内置的属性和方 法,这块空间被称为全局对象 GO。

  • 接着代码执行,最开始执行的是全局代码,为了能够有效区分代码执行时所处的环境会形成一个 EC(G) 全局执行上下文供全局代码执行,在全局执行上下文中有一个存放未来它声明的变量的地 方,叫做 VO(G) 全局变量对象。为了能够在代码执行中,可以访问到 GO 中的属性和方法,浏 览器会在 VO(G) 中默认声明了一个变量 window,值就是 GO 的地址值,从而访问内置的属性 和方法。

  • EC(G) 进入到 ECStack 中执行

  • 变量提升和词法分析

  • 代码执行

  • 遇到函数产生私有上下文

  • 遇到函数和对象以外的花括号产生块级上下文

堆 vs 栈

  • 存储大小

    栈内存的存储大小是固定的,申请时由系统自动分配内存空间,运行效率比较高

    堆内存的存储大小是不定的,由程序员自己申请,运行效率比较低。

  • 存储内容

    栈内存的是基本数据类型,是按值访问的,栈是连续的一块内存空间,以后进先出的原则存储调用。

    堆存储的是引用数据类型的地址值,是不连续的内存空间

  • 回收

    栈的回收是系统控制实现的,只要结束就直接回收。

    堆的回收是由 V8 回收机制控制的

/* VO(G) VS GO 在全局上下文中(前提是全局上下文)

var a = 12
  1.先创建一个值12,因为是var声明,所以存储到GO当中
  2.再创建一个变量a,把其存储GO中
  3.最后把创建的变量和创建的值12关联在一起(赋值操作)

function fn () {}
  1.内存中开辟一个堆内存,每一个堆内存都有一个16进制地址,存储的函数体中的代码串
    把堆内存的地址放到栈内存中,用来供变量的引用
  2.GO中创建一个变量
  3.让GO中变量和之前创建的堆内存地址关联起来

  在没有ES6的时候,var/function是既往GO放一份,也往VO放一份,一个变化另一个也会变化,映射和同步
  ES6诞生后,浏览器既要兼容ES6,也要兼容ES5,为了能够有效区分,ES5声明的都只放到GO中,ES6声明的放到VO中

let b = 12
  1.先创建一个值12,基本类型值直接存储在栈内存VO(GLOBAL)当中
  2.再创建一个变量b,把其存储到VO(GLOBAL)中
  3.最后把创建的变量和创建的值12关联在一起(赋值操作)

let obj = {}
  1.内存中开辟一个堆内存,每一个堆内存都有一个16进制地址,把对象中的键值对分别存储到堆内存中
    把堆内存的地址放到栈内存中,用来供变量的引用
  2.创建一个变量
  3.让变量和之前创建的堆内存地址关联起来

z = 14
  <=> 向当前或上级作用域查找z 到最后都没找到就是window.z = 14

在全局上下文中
  如果window.z,直接到GO中找,没找到就是undefined
  如果直接输出一个变量,先让VO(G)中是否有,如果有获取的就是全局变量,如果没有则去GO中找,
  如果有就是全局对象属性,没有则直接报错 xxx is not defined

数据类型区别 基本数据类型结构比较简单,直接存储到栈内存即可,后续变量都是直接关联和操作这个值 => 按值操作 引用数据类型结构比较复杂,不能直接存储到栈内存中,需要在堆内存中单独开辟一块空间, 用来存储对象的键值对,而变量关联和操作都是堆内存空间的引用地址(16地址),是按引用地址操作 */

js
// example1
let a = {
  n: 1
}
let b = a
a.x = a = {
  n: 2
}
console.log(a.x)
console.log(b) 

// example 2
let a = {},
  b = '0',
  c = 0

a[b] = '1' 
a[c] = '2' 
console.log(a[b]) 

// example 3
let a = {},
  b = Symbol('1'),
  c = Symbol('1')

a[b] = '2'
a[c] = '3'
console.log(a[b]) 

// example 4
let a = {},
  b = {
    n: '1'
  },
  c = {
    m: '2'
  }

a[b] = '3'
a[c] = '4' 
console.log(a[b]) 

// example5
var a = 0
var b = a
b++
console.log(a)
var o = {}
o.a = 0
var b = 0
b.a = 10
console.log(o.a)

// example6
let x = [1, 2, 3]
let y = x
let z = [4, 5, 6]
y[0] = 10
y = z
z[1] = 20
x[2] = z = 30
console.log(x, y, z)