一、基本类型与引用过类型
说到js的变量就不得不说js变量的的类型,js变量分为两个类型,基本类型和引用类型。基本类型包括Undefind、Null、Boolean、Number、String。引用类型包括Object、Array、Date、RegExp、Function、基本包装类型(Boolean/Number/String可能此处有些疑惑,稍后解释)、单体内置对象
基本类型与引用类型的一个很大区别在于:基本类型具有固定大小的空间,因此被保存在栈内存中,基本变量是可以按值访问的,可以直接操作变量实际的值。引用类型是保存在堆当中的,操作对象时采用的是操作对象的引用,而不是实际的值。按照我的理解就是类似于c语言当中的基本类型,在函数传参时可以提现出来,基本类型是传值,而引用类型是传址。
具体区别如下:
1、引用类型具有动态的属性,而基本类型没有
由于基本类型保存在栈里面,具有固定的空间大小,所有无法给基本类型添加额外的属性,但是引用类型存在在堆里面,可以创建额外的空间(可以理解为c语言当中的malloc()函数,但是js在这方面做得很好,你不用担心复杂的内存管理,js有自己的内存管理机制,后面可以了解到),所以可以具有动态的属性。
eg:
var person =new Object();
person.name ="周运金"
alert("person.name"); //周运金
2、复制变量值
基本变量复制时是完全创建一个新的变量,然后把右值复制给新变量的右值,两个变量完全独立,互不影响。但是引用类型的变量复制时,会产生一个副本(指针),这个指针指向的是原对象值的地址空间,也就是指向同一个堆内存地址,只要其中一个变量修改了内存中的数据,另一个也会跟着改变。也就是c语言当中的传址操作。
eg: var obj1 =new Object();
但是有一点需要注意,两个变量除了指向同一个地址空间外,其实两个变量是独立的,自由的,obj2可以指向另一个地址,而这之后就跟obj1没有任何关系了,也不贵影响到obj1(接着上面的代码)
eg:
var obj3 ={
name:"周运金"
}
obj2 =obj3;
alert(obj1.name); //李佳家
3、参数传递
其实参数传递跟复制变量的原理是一样的;
4、检测类型
基本类型(null除外,typeof(null) =object)的检测采用typeof操作符、引用类型的变量(包括null)检测采用instanceof
eg:
alert(person intsanceof Object); //变量是否Object
alert(colors instanceof Array);
alert(pattern instanceof RegExp);
二、执行环境与作用域
i: 执行环境:执行环境定义了变量和函数有权访问其他数据,决定他们各自的行为。每个执行环境都有一个变量对象,环境中定义的变量和函数都在这个不可访问的对象中。这是js自己的机制。
ii: windows对象浏览器默认的全局执行环境。所有的全局变量和函数都是作为windows对象的属性和函数。环境被销魂保存其中的变量与函数也会被销毁全局执行环境只有在关闭网页或者浏览器时才被销毁。
iii:作用域链:用来保持对执行环境中变量与函数访问的顺序的。采用就近原则,作用域的前端都是当前执行代码所在环境的变量。一直延续到全局执行环境。
eg:
var color ="blue";
function changecolor(){
var aColor ="red";
function sColors(){
var tColor =aColor;
aColor=color;
color=tColor;
//此处可以访问所有变量
}
sColors(); //可以访问color和aColor但是不能访问tColor
}
changeColor(); //只能访问color
eg:
var color ="blue";
function getColor()
{
var color ="red";
}
alert(getColor()); //red 根据作用链的顺序来执行
三、js没有块级作用域
块级作用域:我的理解是,在一个花括号里面包围的环境就是一个作用域。在类C语言中,用花括号括起来的就是一个作用域。就比如一个if语句,里面执行的代码执行完之后就会被销毁,如同函数一般。但是在js里面不管用了,因为js没有块级作用域,也就是说,if里面执行的语句其实是包括在代码最近的一个执行对象里面。直接上代码吧
if(true)
{
var color ="blue";
}
alert(color); //blue
for (var i=0;i<10;i++)
{
}
alert(i); //10
四、js垃圾收集机制
这个是js的一大特点,这个特点使得js不像c语言一样要手动跟踪内存使用情况。js的执行环境可以管理代码执行过程中使用的内存,开发人员不用关心内存的使用问题,所需内存的分配,和回收完全实现了自动化管理。其中就涉及到两种内存回收机制:
1、标记清除(最常用)
垃圾收集器在运行时会给存储在内存中的所有变量加上标记。然后它会去掉环境中变量以及被环境中变量引用的标记。而在此之后再被加上标记的变量将被视为准备删除的变量。最后删除那些被标记的变量
2、引用计数(IE)
引用次数为0时删除变量。当变量定义是引用次数为1,赋值给另一个变量引用次数加1,想反,包含这个值引用的变量又取得一个值,则这个值得引用次数减1。但是会造成循环引用的后果。
eg:
function problem()
{
var obj1= new Object();
var obj2 =new Object();
obj1.someOtherObject =obj2;
obj2.someOtherObject =obj1;
}
五、垃圾回收机制的性能问题
垃圾回收机制是周期性进行的,所以确定这个周期是非常重要的。但是IE7以前的浏览器有个很严重问题,他是采用触发机制的,当达到一个临界值就触发垃圾回收。比如256个变量、4096个对象或者数组、或者64kb字符串。如果一个脚本在他的生命周期一直保持这么多变量,垃圾回收就会频繁工作。后面做了改进,当内存分配少于15%时临界值会加倍。
六、内存管理
虽然说js帮我们做了很多内存管理的工作,但是由于浏览器分配的内存比较少,我们还是应该合理地运用,对于一些不必再用的数据可以将值设置为null(离开执行环境,以便垃圾回收器下次运行时回收),主要针对一些全局变量和全局对象的属性。局部属性的话垃圾回收器他自己会懂得。
eg:
function createPerson(name)
{
var localPerson =new Object();
localPerson.name=name;
return localPerson;
}
var globalPerson =createPerson("周运金");
alert(globalPerson.name);
globalPerson =null; //解除引用