js作用域
一、js中的数据类型
基本数据类型:
number、string、boolean、underfined、null
引用数据类型:
object:{}、[]、/$/、Date
function
基本数据类型和引用数据的本质区别:基本数据类型是按照具体的值来操作的,引用数据类型是按照引用地址来操作的
(1)全局作用域: 浏览器加载HTML代码的时候,首先会形成一个供全局js代码执行的环境,我们称之为全局作用域即window,后台用globe表示;
(2)域解释:亦称变量提升,指的是在当前作用域环境中,浏览器会将默认的带var关键字和function关键字的提前声明或者定义;对于带var关键字的浏览器只会提前声明但是不会定义,但是带function关键字的浏览器会提前的声明和定义,发生在栈内存;在es6中基于let或者const不存在变量提升机制
(3)js中内存的分类:
栈内存:用来提供一个js代码执行的环境—>作用域(全局作用域和私有作用域);
堆内存:用来存储引用数据类型的值,对象存储的是属性名及属性值,函数存储的是代码字符串;
(4)全局变量:在全局作用域中(全局作用域域解释的时候)声明的变量是全局变量
(5)私有变量(只有在函数体内):在私有作用域中声明的变量和函数形参是私有变量
(6)作用域链:在私有作用域中,代码执行的时候,遇到了一个变量,首先我们得确定该变量是不是私有变量(首先确定是不是函数形参,其次看有没有带var关键字,如果有其一则是私有的),如果是私有变量则和外面声明的变量没有任何关系,如果不是则在当前作用域上级作用域查找,如果找不到则继续向上级作用域查找,一直找到window作用域为止,这种查找机制称为作用域链
(7)闭包:函数执行的时候会形成一个私有作用域空间,保护了函数里面声明的私有变量,我们将这种机制称之为闭包
(8)在全局作用域中变量带var和不带var的区别:带var的会进行域解释,在变量定义之前输出,浏览器会输出underfined,不带var的在前面输出会报错(...not defined),在后面输出类似于给window增加一个属性名
var num = 12,
var obj = {name:“ywx354980”,age = 23};
function fn(){
var num1 = 22;
console.log("hello world!");
}
(9)自执行函数:函数的定义和执行同时完成。不会参与域解释。
(10)函数体中带return,下面的代码虽然不会执行,但是会进行域解释。
(11)在js代码中如果声明的变量名字和函数名重复,则也算冲突,在域解释的时候下面的不会重新声明,但是会重新赋值。
(12)如何查找上级作用域:看当前函数在哪个作用域下定义的和在哪执行的没关系。
(13)栈内存回收:函数数据类型或者对象数据类型在定义的时候首选会生成一个堆内存空间,堆内存会有一个引用地址,当变量知道了这个地址,我们就认为该内存被占用了,如果想要销毁的话只需将当前变量赋值为null,这样浏览器会在空闲的时候自动回收。
(14)堆内存回收:全局作用域一直不会被销毁,直到关闭浏览器。私有作用域一般情况下函数执行完之后就销毁。不销毁的情况:
a、当前作用域中的部分内容被作用域以外的内存占用了,则当前作用域不销毁,可以理解为函数执行时返回了一个引用类型的值,并且被一个变量接收了返回值,则当前函数执行所形成的作用域不能销毁。如:
function fn()
{
var num = 12;
return function()
{
// code
}
}
var a = fn(); 或者 fn()();
b、在私有作用域中给dom对象绑定了事件方法,则当前私有作用域不销毁。
c、以下情况不立即销毁。
function fn()
{
var num = 12;
return function()
{
// code
}
}
fn()(); // 首先fn执行,会返回一个小函数对应的内存地址,然后接着让小函数返回的小函数再执行完后才销毁。