判断数据类型
- typeof a ——> 不能判断null和引用类型
- a instanceof Array ——> 用来判断对象的具体类型
- Object.prototype.toString.call(a)
数据、变量、内存
数据
数据就是存储在内存中表示特定信息的“内容”,本质就是0101...
数据的特点:可传递、可运算
变量
变量就是可变化的量。由变量名和变量值组成
每个变量都对应一块小内存,变量名用来查找对应的内存,变量值就是内存中保存的数据
内存
内存就是内存条通电后产生的可临时存储数据的空间
数据、变量和内存之间的关系
内存是用来存储数据的临时空间;变量是内存的标识
变量提升和函数提升
变量声明提升
使用var定义(声明)的变量,在变量声明之前就可以访问到,此时值为 undefined
函数声明提升
使用function声明的函数,在函数声明之前就可以调用它,此时值为 函数定义内容
备注:先执行变量提升再执行函数提升
执行上下文
全局执行上下文
- 在执行全局代码前,将window设置为全局执行上下文
- 对全局数据进行预处理
- var定义的全局变量 ===》值为undefined ===》添加为window的属性
- function声明的全局函数 ===》值为函数定义 ===》添加为window的方法
- this ===》赋值为window
- 开始执行全局代码
函数执行上下文
- 在调用函数,准备执行函数体前,创建对应的函数执行上下文
- 对局部函数进行预处理
- 形参变量 ===》赋值为实参 ===》添加为执行上下文的属性
- arguments ===》赋值为实参列表 ===》添加为执行上下文的属性
- var定义的布局变量 ===》值为undefined ===》添加为执行上下文的属性
- function声明的函数 ===》值为函数定义 ===》添加为执行上下文的方法
- this ===》赋值为函数调用的对象
- 开始执行函数体代码
执行上下文栈(后进先出)
- 在全局代码执行前,JS引擎就会创建一个栈来存储管理所有的执行上下文对象
- 在全局执行上下文(window)确定后,将其添加到栈中(压栈)
- 在函数执行上下文确定后,将其添加到栈中(压栈)
- 在当前函数执行完成后,将栈顶的对象移除(出栈)
- 当所有的代码执行完成后,栈中只剩下window
作用域和执行上下文对比
-
区别1:全局作用域外,每个函数都会创建自己的作用域,作用域在函数定义的时候就已经确定了;全局执行上下文是在全局作用域确定后JS代码马上执行之前创建;函数执行上下文是在函数调用时函数体代码执行之前创建
-
区别2:作用域是静态的,只要函数定义好了就一直存在且不会再变化;执行上下文是动态的,是函数调用时创建,函数执行完成后就会自动释放
-
联系:执行上下文是从属于所在的作用域的。全局执行上下文从属于全局作用域;函数执行上下文从属于所在的函数作用域
闭包
什么是闭包
闭包就是一个嵌套的内部函数引用了嵌套的外部函数的变量或函数,就产生了闭包
闭包产生的条件
函数嵌套;内部函数引用了外部函数的变量或函数
常见的闭包
将函数作为另一个函数的返回值; 将函数作为参数传入另一个函数
闭包的优点
- 使用函数的内部变量,在函数执行完以后依然存在于内存中,延迟了局部变量的生命周期;
- 让函数外部可以操作函数内部的变量或函数
闭包的缺点
由于函数执行完成后,函数内部的变量依然存在于内存中没有释放,占用内存时间会变成,容易造成内存泄露
内存溢出与内存泄露
内存溢出
内存溢出是一种程序运行出现的错误。当程序运行需要的内存超过了剩余内存时,就会抛出内存溢出的错误
内存泄露
内存泄露是指占用的内存没有及时释放
内存泄露积累的多了就会出现内存溢出
常见的内存泄露包括:意外的全局变量;没有及时清理的定时器或回调函数;闭包