加强信息管理 维护网站建设/太原自动seo
变量、作用域
- 一、基本类型和引用类型的值
- 1.动态的属性
- 2.复制变量值
- 3.传递参数
- 4.检测类型
- 二、执行环境及作用域
- 1.执行环境
- 2.延长作用域链
- 2.没有块级作用域
一、基本类型和引用类型的值
基本类型值指的是简单的数据段,而引用类型值指的是那些可能由多个值构成的对象。
引用类型的值是保存在内存中的对象,JavaScript不允许直接访问内存的位置,也就是不能直接操作对象的内存空间,引用类型的值是按引用访问的。
1.动态的属性
var person = new Object();
person.name = "Nicholas";
alert(person.name); //"Nicholas"
以上代码创建了一个对象并将其保存在了变量person中。然后,又加上一个名为name的属性,并且将字符串值"Nicholas"赋给了这个属性。又通过alert()函数访问了这个新的属性。如果对象不被销毁或者这个属性不被删除,则这个属性将一直存在。
但是不能给基本类型的添加属性。
var name = "Nicholas";
name.age = "27";
alert(name.age); //undefined
因此只能给引用类型值动态的添加属性。
2.复制变量值
- 如果从一个变量向另一个变量复制基本类型的值,会在变量对象上创建一个新值,然后把该值复制到为新变量分配的位置上。两个变量是完全独立的,可以参与任何操作而不会相会影响。
- 当从一个变量向另一个变量复制引用类型的值时,同样也会将存储在变量对象中的值复制一份放到新变量分配的空间中。**这个值的副本实际上是一个指针,而这个指针指向存储在堆中的一个对象。**复制操作结束后,两个实际上将引用同一个对象。因此,改变其中一个变量,就影响另一个变量。
3.传递参数
ECMAScript中所有函数的参数都是按值传递的。基本类型值的传递如同基本类型变量的复制一样,而引用类型值得传递,则如同引用类型变量的复制一样。参数只能按值传递。
4.检测类型
如果变量的值是一个对象或null,则typeof操作符会像下面例子中所示的那样返回"object";
var s = "Nicholas";
var b = true;
var i = 22;
var u;
var n = null;
var o = new Object();alert(typeof s); //string
alert(typeof i); //number
alert(typeof b); //boolean
alert(typeof u); //undefined
alert(typeof n); //object
alert(typeof o); //object
如果变量是给定引用类型的实例,那么instanceof操作符就会返回true。
alert(perosn instanceof Object); //变量person是Object吗?
alert(colors instanceof Array); //变量colors是Array吗?
alert(pattern instanceof RegExp); //变量pattern是RegExp吗?
在检测一个引用类型值和Object构造函数时,instanceof操作符始终就会返回true。当然如果使用instanceof操作符检测基本类型的值,则该操作符始终会返回false,因为基本类型不是对象。
使用typeof操作符检测函数时,该操作符会返回"function"。
二、执行环境及作用域
1.执行环境
每一个函数都有自己的执行环境。当执行流入一个函数时,函数的环境就会被推入一个环境栈中。当代码在一个环境中执行时,会创建变量对象的一个作用域链。作用域链的用途是保证对执行环境有权访问的所有变量和函数的有序访问。
作用域链的前端始终都是当前执行的代码所在环境的变量对象。全局执行环境的变量对象始终都是作用域链中的最后一个对象。
var color = "bule";
function changeColor(){var anotherColor = "red";function swapColors(){var tempColor = anotherColor;anotherColor = color;color = tempColor;//这里可以访问color,anotherColor和tempColor}//这里可以访问color,anotherColor,但不能访问tempColorswapColors();
}
//这里只能访问color
changeColor();
==内部环境可以通过作用域链访问所有的外部环境,但外部环境不能访问内部环境中的任何变量和函数。==这些环境之间的联系是线性、有次序的。每一个环境都可以向上搜索作用域链,以查询变量和函数名,但任何环境都不能通过向下搜索作用域链而进入另一个执行环境。
函数参数也被当做变量来对待,因此其访问规则与执行环境中的其他变量相同。
2.延长作用域链
当执行流进入下列任何一个语句时,作用域链就会得到加长。
①try-catch语句的catch块。
②with语句。
这两个语句都会在作用域链的前面添加一个变量对象。
对with语句来说,会将指定的对象添加到作用域链中,对catch语句来说,会创建一个新的变量对象,其中包含的是被抛出的错误对象的声明。
function buildUrl(){var qs = "?debug=true";with(location){var url = href+qs;}return url;
}
with语句接受的是location对象,因此其变量对象中就包含了location对象的所有属性和方法,而这个变量对象被添加到了作用域链的前端。buildUrl()函数中定义了一个变量qs。当在with语句中引用href时,可以在当前执行环境的变量对象中找到。
当引用变量qs时,引用的则是在buildUrl()中定义的那个变量,而该变量位于函数环境的变量对象中。至于with语句内部,则定义一个名为url的变量,因而url就成了函数执行环境的一部分,所以可以作为函数的值被返回。
2.没有块级作用域
if(true){var color="blue";
}
alert(color); //"bule"
在JavaScript中,if语句中的变量声明会将变量添加到当前的执行环境(这里指的是全局环境)中。
for(var i=0;i<10;i++){doSomething(i);
}
alert(i); //10
在JavaScript中由for语句创建的变量i即使在for循环执行结束后,也依旧会存在于循环外部的执行环境中。
- 声明变量
使用var声明的变量会自动被添加到最近的环境中。在函数内部,最接近的环境就是函数的局部环境,在with语句中,最接近的环境是函数环境。如果初始化变量时没有使用var声明,该变量会自动被添加到全局环境。 - 查询标识符
搜索过程中从作用域链的前端开始,向上逐级查询与给定名字匹配的标识符。在搜索过程中如果存在一个局部的变量的定义,则搜索会自动停止,不再进入另一个变量对象。换句话说,如果局部环境中存在着同名标识符,就不会使用位于父环境中的标识符。