1.变量
基本类型:数字、字符串、布尔值、undefined
、null
引用类型:[数组]
、{对象}
区别:基本类型的值不能修改(可以通过覆盖的形式进行变更),引用类型的值可以修改(可以改变其本身的值)
基本类型为什么可以调用方法?类似于’string’.replace(‘s’,’’)?
基本类型调用方法时会找到其包装类(数字的包装类是Number,字符串的包装类为String),调用其包装类的属性和方法,其本身并没有属性和方法。
变量在内存中如何保存?
基本类型保存在栈内存(有序,固定大小)中,引用类型保存在堆内存(无序、不固定大小)中,其地址保存在栈内存中(因为地址大小固定)
两种变量访问方式
按值访问、按引用访问
变量相等的比较
基本变量比较值,值相等即相等。
引用类型比较,引用指向同一块内存才相等。
变量值的复制
基本类型直接使用变量名进行赋值操作即可复制值。
引用类型复制需要遍历属性进行复制。
如何检测数据类型?
使用typeof()方法
使用引用名 instanceof 类名
判断,注意此方法只能判断引用类型
2.作用域
2.1 全局作用域
函数体外的变量叫做全局变量,在全局作用域中均可访问。
2.2 局部作用域:函数作用域
函数体内的变量叫做局部变量,只能在其所处的函数作用域内访问。
2.3 作用域链
2.4 延长作用域链
延长作用于链就是在全局作用域(window作用域)中创造一个小的作用域,以达到延长作用域链的效果。不推荐使用。
2.5 JS解析机制:预解析
打印结果为undefined
JS的解析过程:
(1)预解析
查找window
作用域下的所有var
变量,并给这些变量赋默认值undefined
。再查找function
关键字,直接将函数加载(不赋值、不解析,只声明)
预解析是,函数名和变量名冲突时,保留函数;两个函数名冲突,保留最后出现的函数。
(2)逐行解读代码
遇到函数会跳过(因为预解析时已经声明),知道遇到函数调用的语句。
看几个问题加深理解:
问题1:
console.log(a);
var a=1;
//undefined
console.log(a);
a=1;
//报错,因为无法预解析a
问题2:
console.log(a);
var a=1;
console.log(a);
function a(){
console.log(2);
}
console.log(a);
var a=3;
console.log(a);
function a(){
console.log(4);
}
console.log(a);
a();
解析过程:
~~var a=undefined;//a=3那一行~~
a是一个函数//log(4)的那一个函数
---预解析完成---
a()
1
函数跳过
1
3
函数跳过
3
遇到函数调用语句:a不是函数,因此报错
问题3:
<script>
console.log(a)
</script>
<script>
var a=1;
</script>
报错,因为两个script
标签分别预解析,即第一个标签内预解析完之后(打印之后),才解析第二个标签。
<script>
var a=1;
</script>
<script>
console.log(a)
</script>
打印1,因为a是一个全局变量。
问题4.1:
var a=1;
function fn(){
console.log(a);
var a=2;
}
fn();
console.log(a);
打印结果:
undefined
1
解析过程:
a=undefined
fu()
a=undefined
---预解析完成---
a=1
fn()跳过
fn(),根据作用域链,打印函数体内部的a,即undefined
打印全局变量a=1
问题4.2:
var a=1;
function fn(){
console.log(a);
a=2;
}
fn();
console.log(a);
打印结果:
1
2
解析过程:
a=undefined
fu()
函数内部的a为全局变量,没有var,因此不做预解析
---预解析完成---
a=1
fn()跳过
fn(),根据作用域链,此时函数体内部没有预解析的a,因此打印的是全局变量a=1
函数体内,全局变量被赋值为2
打印全局变量a=2
问题4.3:
var a=1;
function fn(a){
console.log(a);
a=2;
}
fn();
console.log(a);
打印结果:
undefined
1
解析过程:
a=undefined
fu(a)对参数进行预解析 参数a=undefined
函数内部的a此时为参数
---预解析完成---
a=1
fn(a)跳过
fn(a),根据作用域链,打印函数体内部的参数a,即undefined
函数体内,参数被赋值为2
打印全局变量a=1
问题4.4:
var a=1;
function fn(a){
console.log(a);
a=2;
}
fn(a);
console.log(a);
打印结果:
1
1
解析过程:
a=undefined
fu(a)对参数进行预解析 参数a=undefined
函数内部的a此时为参数
---预解析完成---
a=1
fn(a)跳过
fn(a),根据作用域链,a=1作为参数被传入函数体内部
打印参数a=1
函数体内,参数被赋值为2
打印全局变量a=1
3. JS垃圾收集机制
目标:释放无用数据,回收内存
原理:找出没有用的数据,打上标记,释放其内存;周期性执行
标识无用数据的策略:
标记清除:离开作用域的变量将被清除。
引用计数:引用次数变为0即可回收内存。