基础数据值在内存中占据固定的大小空间,所以存在栈内存中
js的执行上下文顺序借用了栈数据的存取方式,因此理解栈数据结构的原理和特色十分重要
方式:先进后出,后进先出(相似一盒乒乓球)前端
引用类型的值是对象,保存在堆内存中
堆数据结构是一种树状结构,它的存取方式,则与口红色号同样,只要有色号,就能找到对应的口红
没必要像乒乓球把上面的都拿出来才能获取中间的某一个
比如JSON格式,key:value能够是无序的,由于顺序的不一样不影响咱们的使用,咱们只关心色号编程
学习队列数据结构的目的主要是为了清晰的明白咱们js中事件循环(Event Loop)
队列是一种先进先出的数据结构,正如排队过安检是同样的。排在最前面的人必定是最早过安检的人。数组
js执行上下文以后,会建立一个叫变量对象的特殊对象,js的基础数据类型每每保存在变量对象中
基础类型都是一些简单的数据段,因此基础数据类型是按值来访问的,咱们能够直接操做变量对象的实际值浏览器
js的引用类型储存在堆内存中
js不容许咱们直接访问内存中的数据
世界上咱们操做的是对象的引用而非实际的值
引用类型是按指针访问的,这个指针指向内存中的实际地址。
所以,咱们操做引用类型复制时,它一样会分配一个新的值保存在变量对象中,但这个个新值一样指向内存中的实际值。改变一个,另外一个也会发生改变性能优化
分配你所需的内存
使用分配的内存(读写)
不须要时释放,归还数据结构
js拥有自动垃圾会回收机制
经常使用的使用标记清除法
当变量进入环境时,就将这个变量标记为进入环境
垃圾回收机制运行中会给存储在内存中的变量添加标记。而后,去掉环境中的变量以及环境中的变量被引用的标记,而在此以后再加上标记的变量将视为被准备删除的变量闭包
避免全局变量,使用完及时清空
局部变量,当函数执行安成以后很容易作出判断,而后回收。app
执行上下文的顺序是栈的数据结构方式,先进后出,后进先出
基础数据类型的值存在栈内存中
引用数据类型的值存在堆内存中
队列数据结构先进先出,后进后出。事件循环机制(Event Loop)
从一个变量向另外一个变量复制基本类型的值。会建立这个值的副本
从一个变量向另外一个变量复制引用类型的值,复制的实际上是指针,所以两个变量最后指向同一个对象
解除变量的引用不只有助于消除循环引用现象,并且对垃圾收集也有好处。为了确保有效地回收内存,应该及时解除再也不使用的全局对象、全局对象属性以及循环引用变量的引用。函数式编程
每当控制器转到可执行代码的时候,就会进入一个执行上下文
它会造成一个做用域,js运行环境分为3个种状况
全局做用域
函数做用域
eval
执行上下文能够理解成为当前代码的执行环境
所以js程序会出现多个执行上下文,因此js用栈的方式去处理它们。这个栈就叫作函数调用栈。栈底永远是全局上下文,栈顶是当前执行上下文函数
建立变量对象(vo)
创建做用域链(scopechain)
肯定this指向
变量赋值
函数引用
执行其余代码
js是单线程
同步执行,只有栈顶的上下文处于执行中,其余上下文须要等待,
全局上下文只有一个,它在浏览器关闭的时候出栈
函数执行上下文没有数量限制
每次新函数被调用,就会有新的执行上下文被建立
变量对象是执行上下文的建立阶段,会建立一个叫变量对象的基础对象。js的基本类型每每都保存在变量对象中
变量对象的生命周期是根据执行上下文的生命周期去划分的
建立阶段:(变量提高阶段,变量对象中的属性不能访问)
建立arguments对象
检查function函数声明建立属性
检查var变量声明的属性
执行阶段(变量对象转为活动对象,属性能够被访问,开始函数执行阶段操做)
函数执行
变量赋值
弹出执行栈
活动对象和遍变量对象实际上是同一个的对象,区别在于执行的上下文的生命周期不一样。
建立阶段就是变量对象,变量对象的属性不可被访问。
执行阶段就是活动对象,处于函数调用栈栈顶,也就是当前执行上下文。
这里以浏览器为例,全局对象是window
全局上下文存在一个特殊的地方,他的变量对象就是window,而这个特殊的对象在this指向一样适用,this也指向window
全局上下文的生命周期与程序的生命周期同样,只要浏览器窗口不关闭,它就会一直存在。其余环境的上下文环境均可以访问全局上下文
不存在变量提高
未声明不能够用 (暂时性死区)
做用域也就是词法环境
词法环境就是一中规范的类型,用于ECMAscript代码的词法嵌套结构来定义标识符与特定变量和函数的关联
做用域是一种规则,做用域链是代码在执行的过程当中,会动态变化的一条索引路径
由当前环境和上层环境的一些列变量对象组成,它保证了当前执行环境对符合访问权限的变量和函数的有序访问
闭包是一种特殊的对象
由2部分组成
执行上下文(A)
以及执行上下文中建立的函数(B)
当B执行时,若是访问了A中变量对象中的值。就像成了闭包
垃圾回收机制,js具备自动垃圾回收机制,当一个值在内存中失去引用时,垃圾回收器很快找到它,并回收释放
函数执行上下文在执行完毕后,生命周期结束后,垃圾回收器就是收回其占用的内存空间,但使用闭包就会阻止这个过程
全局的this,指向window
经过this绑定到全局对象
经过声明绑定到变量对象,但在全局环境中,变量对象就是它自身
仅仅只有赋值操做,标识符会隐式绑定到全局对象
若是函数调用者,被某一个对象拥有。那么该函数在调用时,this就是指向这个对象
若是函数内部独立调用,那么该函数内部的this,则指向window,严格模式下指向undefind
js内部提供了一种机制,容许咱们改变thiss的指向。他就是call和apply
这2个函数的第一个参数都是改变this的指向,区别:
在于第二个参数,call接受一个个参数传入
apply接受数组传入
接受参是一个个传入
参数接受一个数组
返回一个函数
能够选择不当即执行
apply和call是当即执行
函数声明
function fn(){}
函数表达式
let fn=function(){}
匿名函数
function add(fn,num){console.log(fn()+num)}
add(()=>90,10)
自执行函数
(()=>console.log(90))()
基本类型复制是值进行的复制,复制后互不影响
引用类型的复制是指针的复制。虽然也在变量对象上开辟新的空间,但实际指针同样是堆内存中的地址,其中一个改变,另外一个也将改变,相互影响
函数是一等公民
只用表达式,不该语句
纯函数
没有办法识别对象实例的类型
经过一个方法能够去生成多个须要的对象
解决了重复代码编写
使用new的方式。经过原型链找到对象的实例对象
new的四部曲
建立一个对象
将这个对象的原型指向构造函数的原型
经过apply将构造函数的的this指向这个对象
最后返回这个对象
私有方法放实例中
共有方法放到原型链上
原型的好处是避免了同一功能性的方法写多份。直接挂载到原型上便可
当咱们访问实例对象中的属性或者方法时,会优先访问实例对象自身的属性和方法。
原型链的访问,其实跟做用域链有很大的类似之处,他们都是一次单向的查找过程。所以实例对象可以经过原型链,访问处处于原型链上对象的全部属性与方法
首先是构造函数的继承
经过call将父级的指针指向子集
原型的继承
能够将子集的原型指向父级的实例
使用Object.create
configurable是否能够被删除
enumerable是否能够被枚举
writable是否能够重写
value该值具体多少,默认undefind
get访问,获取属性值
set设置。设置属性值
不能同时设置value、writable 与 get、set的值。
读取属性Object.getOwnPropertyDescriptor
js是单线程,这个线程拥有的惟一的事件循环
来自不一样任务源的任务会进入到不一样的任务队列。其中setTimeout与setInterval是同源的。
事件执行的顺序,决定了JavaScript代码的执行顺序
它从script(总体代码)开始第一次循环,
以后全局上下文进入函数调用栈。直到调用栈清空(只剩全局),
而后执行全部的micro-task。
当全部可执行的micro-task执行完毕以后。
循环再次从macro-task开始,找到其中一个任务队列执行完毕,而后再执行全部的micro-task,这样一直循环下去。
其中每个任务的执行,不管是macro-task仍是micro-task,都是借助函数调用栈来完成
setTimeout
setInterval
script(总体代码)
Promise
XMind: ZEN - Trial Version