深入了解javascript(二)
在上篇的深入了解javascript(一)当中留过一个问题
源代码是和结果这样的


注意两张图片的区别。



变量、作用域和内存的问题
1、js分为基本类型和引用类型,1)基本类型包括null、undefined、string、number、boolean,这些基本类型的值可以直接操作保存在变量中实际的值 2)而js不能直接操作对象的内存空间,实际操作的是对象的引用(地址),常见的引用类型object 、function、array、date、RegExp、Error
2、定义引用类型(对象,以下称为对象),创建的方法与基本类型一致,都是创建一个变量对象围棋赋值,但它们的区别是,对象有自己的属性和方法,如果对象不销毁的话,其属性将一直存在。比如 var person=new Object(); person.name="nanlan"; alert(person.name);
3、传递参数。ECMAscript当中所有函数的参数只能通过值传递,而其他的则有按值传递和引用传递。比如:
1)基本类型的值传递
function sum(num){
num+=10; return num;
}
var count=20;
var result=sum(count);
alert(count); //20; 沒有变化 alert(result); 30
基本类型的按值传递参数相对来说比较简单,下面我们看看对象的参数传递
2)引用类型(对象)的值传递
function setname(obj){
obj.name="nanlan";
}
var person = new Object();
person.name= "xiaoju";
setName(person);
alert(person.name); //nanlan

看到了没,基本类型和引用类型的区别,这是因为setName函数里面的obj和person指的是同一个对象(在堆内存当中),而且是全局对象。很多人会觉得局部作用域中修改参数在全部函数中体现出来,就是按引用传递,为了证明是按值传递的,我们再看看以下的例子

如果person是按引用传递的,那么obj就会自动被修改指向新的属性会”xiaoju“,但是原始的值依然不变,这是因为函数内部重写obj,就是一个局部对象,而函数结束之后,局部对象就会被销毁
4、检测类型
typeof 变量名(基本类型) ,我们还可以使用instanceof检测引用类型,但是引用类型的值都是object的实例,那还用instanceof干嘛用,其实我们并不是想知道他是是对象,而是想知道他是什么类型的对象,语法为 : 变量 instanceof array /object/RegExp等,意思就是某个变量是数组吗/对象吗。
在检测引用类型和Obejct的构造函数时,instanceof通常都会返回ture,但是如果是基本类型的话,则会返回false,因为基本类型不是对象

5、執行环境以及作用域
1)全局执行环境被认为是window对象,某个执行环境中的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义也随之销毁(全局变量等到这个应用程序结束之后或者浏览器关闭才会被销毁)
2)全局执行环境的变量对象始终都是作用域链中最后一个对象,举个例子来说
var color = ”blue“;
function changecolor(){
var another = "red";
function swapcolor(){
var tempcolor = anothercolor;
anothercolor = color;
color =tempcolor;
//这里可以访问 color、another、 tempcolor
}
//这里可以访问 another、color
swapcolor();
}
//这里只能访问 color
changecolor();
以上的代码说明一个问题:外部的环境不能访问内部环境的函数和变量,但是内部环境可以访问外部环境(函数有时也会被当作变量来定义)
6、没有块级作用域
值得注意的是,在js当中,如果用if语句声明的变量将会添加到当前执行的环境(全局环境),比如说 if(ture){
var color = "blue";
},而在C、C++、Java当中if语句声明的变量会在if语句结束之后销毁
1)声明变量,var 声明的变量自动被添加到最接近的环境当中;在函数内部,最接近的环境就是局部环境;而在with语句当中,最接近的环境就是函数环境。如果初始化没有用var 关键字声明的话,则这个变量会被添加到全部变量当中
2)查询标识符,搜索的过程从作用域链的前端开始,向上逐级查询与给定名字匹配的标识符,如果在局部环境当中知道了该标识符,搜索过程停止;如果没有找到的话,则向上沿作用域链向上搜索一直到全局变量,如果还是没有,则没有定义