javascript变量、执行环境和作用域
一、变量:变量是在语言中用来存放数据(值)的标识符,会在内存里开辟一定大小的空间,然后把值填充到此空间里,再用变量名(标识符)指向此空间地址,这样访问变量名就能访问到具体的值了。
变量的定义:用关键字var定义,如 var temp = "abc"; 声明变量名为temp并初始化值“abc",其作用域范围则所在的执行环境区域。
变量类型:javascript变量类型分为基本类型和引用类型,基本类型有undefined,null,boolean,string,number 5种,也称为简单数据类型。引用类型只有一种Object,也称为复杂数据类型。
基本类型定义:var temp; var temp = undefined; var temp = 1;
引用类型定义:var obj = new Object(); // 注意大小写
在内存里存储方式:
1.基本类型:

基本类型是占用内存里存的值是真实的值。假设”var varD = varC;",会新开辟一块内存,变量名varD指向该内存,然后把varC中的值复制一份到varD,等于有4块内存区域,互不影响。
2.引用类型:

由上图可以看出,引用类型实质占用2块内存(栈内存和堆内存),栈内存存放指向堆内存地址(16进制表示),而堆内存则真正存对象的真实内容。
基本类型和引用类型的比较:
1.基本类型存放在栈内存里,引用类型存在堆内存里,理论上讲栈内存比堆内存效率更高。
2.从内存占用数量来看,基本类型只占用1个内存块,引用类型占2个内存块。
3.如果需要多个变量之间互相传递,基本类型无疑会不断增加内存块,而引用类型只保持1个真实数据内存,其它都是保存为引用地址。因此,基本类型适合存储最简单的数据结构,而引用类型适合存储复杂的数据结构.(试想下,如果引用类型也存在栈内存,每次对象间赋值,则会复制一份对象,对象通常占用内存较大,可想而知,中间浪费了不少内存)
变量的形态:javascript变量是一种动态变量,即可以在使用过程中随时更改变量类型,如下:
1.
var temp = "abc";
document.write(typeof temp);// 输出String
tmep = 1;
document.write(typeof temp); //输出 Number
动态更改数据类型虽然JS允许,但容易造成开发人员困惑,在开发时还是要求严格方式,变量名的作用意义包括数据类型。
2.
function fun() {
temp = 1;
alert(temp); // 输出1
this.fun2 = function() {
temp2 = 2;
alert(temp2); // 输出2
}
}
alert(temp); //输出1
alert(temp2); // 输出2
如上,在函数范围内声明变量没有加var关键字,则默认为全局变量.
3.
function fun() {
var temp = 1;
alert(temp); // 输出1
this.fun2 = function() {
var temp2 = 2;
alert(temp2); // 输出2
}
}
alert(temp); //抛出 temp 未定义
alert(temp2); // 抛出temp2 未定义
检测引用类型:通过instanceof 关键字判断是否引用类型。如下:
var temp = new Object();
alert(temp instanceof temp); // 返回true
function Student() {
this.name;
}
var stu = new Student();
alert(stu instanceof Student); //返回true
alert(stu instance of Object);//返回true, 因为JS所有引用类型对象都是从Object继承过来的
二、执行环境:javascript执行环境定义了变量或函数能够访问的权限范围,以决定它们各自的行为。JS有2种执行环境,全局执行环境和局部执行环境,在web浏览器中全局执行环境通常用window表示,是最顶级的执行环境。全局执行环境生命周期是从网页加载到网页关闭或关闭整个浏览器。
每个函数都有其执行环境,所有函数的执行环境都叫局部执行环境。其生命周期是从函数开始被调用,到函数体结束(或者说执行return)。
三、作用域:javascript每个变量以及函数(类)都有其作用域(生命周期)。全局变量通常是网页加载到结束,局部变量通常是函数开始调用到结束。下面讲作用域与执行环境关系:
1.
function fun() {
alert(temp);
}
var temp;
fun();
当进入到fun函数时,fun执行环境创建,会在自的执行环境作用域链查找temp变量,当没找到,再从链的父执行环境查找,直到查找到为止。注意:父执行环境不能访问子执行环境。
2.
function fun() {
this.temp;
this.subFun = function() {
this.temp2;
}
alert(this.temp2); // 错误,不允许访问子执行环境
}
块级没有作用域:
if (true) {
var temp = "";
}
alert(temp); //能正确访问, 块级没有作用域,里面定义的temp是外面的执行环境,要特别注意一点,for循环定义的变量执行后是外面的值,如:
for (int i = 0; i < 10; i++) {
}
alert(i); // i = 9;
如果要在函数里访问全局变量,可以用window标识,如
var ta = "abc";
function funA() {
var ta = "bcd";
alert(window.ta);//输出abc
}
浙公网安备 33010602011771号