一、基本类型和引用类型的值
1.1、基本类型
概念:简单的数据段
基本类型:数值型 (number)、字符串型(string)、逻辑型(boolean)、无定义数据类型(undefined)、空值(null);在内存中占据固定的大小空间,被保存在栈内存中。
1.2、引用类型
概念:多个值构成的对象,引用类型的值保存在内存中的对象中,引用类型的值是按引用访问的,因为JS不允许直接访问内存中的位置。
函数(function)、对象(object)、数组 (array);堆内存
引用类型的值是保存在内存中的对象,js不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间。在操作时实际上是在操作对象的引用而不是实际对象。但是当复制保存对象的某个变量时,操作的是对象的引用,但在为对象添加属性时,操作的是实际的对象。
1.2.1、动态的属性
对于引用类型的值,可以为其添加属性和方法,也可以删除其属性和方法,但不能对基本数据类型执行这样的操作,虽然不会引发错误。
1.2.2、复制变量值
基本类型变量的复制对于两个变量参与其他运算并没有影响。
当从一个变量向另一个变量复制引用类型的值时,其实得到的是是一个指针,而这个指针指向存储在堆中的一个对象。复制操作结束后,两个变量实际上将引用同一个对象。因此,改变其中一个变量,就会影响另一个变量。
<script type="text/javascript">
var obj1 = new Object();
obj1.name = 'xushuai';
var obj2 = obj1;
alert(obj2.name);//xushuai
obj2.age = 23;
alert(obj1.age);//23
</script>
1.2.3、传递参数
在向参数传递一个基本类型的值时,此时该值被赋予一个局部变量;在向参数传递引用类型的值时,会把这个值在内存中的地址复制给一个局部变量,此时变化反映在函数的外部。
<script type="text/javascript">
function AddTen(num) {
num += 10;
return num;
}
var count = 20;
AddTen(count);//20
alert(count);
function SetName(obj) {
obj.name = "xushuai";
}
var person = new Object();
SetName(person);
alert(person.name);//xushuai
function SetName1(obj) {
obj.name = "xushuai";
obj = new Object();//在函数内部重写obj时,这个变量引用的就是一个局部对象了
obj.name = "zhuxiao";//这个局部对象会在函数执行完毕后立即被销毁
}
var person1 = new Object();
SetName1(person1);
alert(person1.name);//xushuai
</script>
1.2.4、检测类型
typeof()——确定一个变量是五种基本类型还是引用类型
instanceof()——确定某个值是什么类型的对象,而不仅仅是知道它是个对象。
javascript中的每个对象都有prototype属性,Javascript中对象的prototype属性的解释是:返回对象类型原型的引用。
A.prototype = new B();
理解prototype不应把它和继承混淆。A的prototype为B的一个实例,可以理解A将B中的方法和属性全部克隆了一遍。A能使用B的方法和属性。这里强调的是克隆而不是继承。可以出现这种情况:A的prototype是B的实例,同时B的prototype也是A的实例。
因为Foo的prototype是函数Aoo的一个实例,所以alert出来的两个值都是true。【该段取自作者:jiangqindaiyu 】
二、执行环境及作用域
2.1、执行环境
执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为。每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个无法通过代码访问的对象中,但解析器在处理数据时会在后台使用它。
全局执行环境是最外围的一个执行环境。在Web浏览器中,window对象被认为是全局执行环境,因此所有全局变量和函数都是作为window对象的属性和方法创建的。某个执行环境中的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义也随之销毁。全局执行环境直到应用程序退出时才会被销毁。
每个函数都有自己的执行环境。当执行流进入一个函数时,函数的环境就会被推入一个环境栈中,而在其执行完毕后,栈将其退出环境栈,把控制权返回给之前的执行环境。
而内部环境可以通过作用域链访问所有的外部环境,但外部环境不能访问内部环境中的任何变量和函数。
2.2、作用域
作用域链:保证对执行环境有权访问的所有变量和函数的有序访问。作用域的前端始终都是当前执行的代码所在环境的变量对象。
标识符解析:沿着作用域链一级一级地搜索标识符的过程。
<script type="text/javascript">
var color = "blue";
function changeColor() {
if (color == "blue") {//可以访问到color,因为它在其作用域链的前端
color = "red";
} else {
color = "blue";
}
}
changeColor();
alert("color is now " + color);//color is now red
</script>
以上一共三个环境,全局环境,changeColor()局部环境和swapColor()局部环境。全局环境中有变量color和一个函数changeColor()。局部环境changeColor()中有变量anothercolor和函数swapColor()。swapColor()局部环境中有变量tempColor,该变量只能在这个环境中被访问到。全局环境和changeColor()的局部环境都无法访问tempColor。然而在swapColor()环境中可以访问到其他两个环境中的所有变量。因为那两个环境是它的父执行环境。【取自作者:jiangqindaiyu 】
2.3、延长作用域链
2.3.1、tyr...catch语句的catch块
2.3.2、with语句
2.4、没有块级作用域
<script type="text/javascript">
if (true) {
var color = "red";
}
alert(color);//red color不是应该在if语句执行完毕后被销毁吗?显然没有块级作用域
</script>
三、垃圾收集的两种方式
3.1、标记清除——目前主流的垃圾收集算法
3.2、引用计数
3.3、管理内存
一旦数据不再使用,最好通过将其设置为null来是否引用,这个做法叫做解除引用。