一个完整的JavaScript实现应该由下列三个不同的部分组成:
- 核心(ECMAScript)
- 文档对象模型(DOM)
- 浏览器对象模型(BOM)
ECMAScript
与Web浏览器之间没有依赖关系。实际上,这么语言本身并不包含输入和输出的定义。ECMScript-262定义的只是这门语言的基础,我们常见的Web浏览器只是ECMScript实现的可能的宿主环境之一。ECMAScript标准没有参照Web浏览器,它规定了这门语言的下列组成部分:
1. 语法
2. 类型
3. 语法
4. 关键字
5. 保留字
6. 操作符
7. 对象
文档对象模型(DOM)
文档对象模型(DOM)是针对XML但经过扩展用于HTML的应用程序 编程接口(API)
浏览器对象模型(BOM)
开发人员使用BOM可以控制浏览器显示的页面以外的内容。
变量,作用域和内存的问题
传递参数
先简单说一下两种传递参数的方式:
按值传递:
传递的参数是按值的拷贝传递
按引用传递
指的是在方法调用时,传递的参数是按引用进行传递,其实传递的引用地址就是变量对应的内存空间地址,传递前和传递后都指向同一个引用(也就是同一个内存空间)
ECMAScript中所有的函数的参数都是按值传递的的:
即把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样。
基本类型的传递如同基本类型变量的复制一样,在向参数传递基本类型的值时,被传递的值会被复制给一个局部变量 。
引用类型的传递,则如同引用类型变量的复制一样,在向参数传递引用类型的值时,会把这个值在内存中的地址复制给一个局部变量,因此这个局部变量的变化反映在函数外部
关于基本类型和引用类型的复制可以看一下这篇文章(我尽力进步)JS中变量存储问题
举例:
function setName(obj){
obj.name = "xiaohu";
}
var person new Object();
setName(person);
alert(person.name);
以上代码创建了一个对象,并将其保存在变量person中,然后变量被传递到setName()函数中,person 在内存中的地址值复制给一个变量,所以obj被赋值了一个指向person对象的地址值,可以访问到person对象,所以当在函数内部给obj添加name属性之后,函数外部的person 也会有反映
更生动的例子:
function setName(obj){
obj.name = "Nicholas";//按照obj得到的地址值指向person这个对象的内存地址,给person对象增加了一个name属性
obj = new Object();
//此时变量obj变量被赋予一个新对象,那么此时obj的值是一个指向新对象的地址值
//如果是按照引用传递参数,那么此时person(这个引用)就会被改向指向新对象,那么person的name应该是Bob
obj.name = "Bob";
}
var person = new Object();
setName(person);
alert(person.name);//"Nicholas"
执行环境和作用域
全局执行环境是最外围的一个执行环境。根据ECMAScript实现所在的宿主环境不同,表示执行环境的对象也不一样。在web浏览器中,全局执行环境被认为是window对象,因此所有的全局变量和函数都是作为window对象的属性和方法创建的。某个执行环境的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义也随之销毁(全局执行环境直到应用程序退出——例如关闭网页或者浏览器时才会被销毁)
当代码在一个环境中执行时,会创建变量对象的一个作用域链。作用域链的用途是保证对执行环境有权访问的所有变量和函数的有序访问。作用域链的前端始终都是当前执行的代码所在环境的变量对象。
var color = "blue";//全局环境
function changeColor(){
var anotherColor = "red";
function swapColors(){
var tempColor = anotherColor;
anotherColor = color;
color = tempColor;
//这里可以访问tempColor anotherColor,color
}
//这里可以访问anotherColor和color,但是不能访问tempColor
swapColors();
}
//这里只能访问color
changeColor();
以上代码共涉及三个执行环境:全局环境,changeColor()局部环境和swapColors()局部环境。
全局环境中有一个变量color和一个函数changeColor()的函数,但是它可以访问全局环境中的变量color,swapColors()的局部环境中只有一个变量tempColor,该变量只能在这个环境中访问到。无论全局环境还是changColor()的局部环境都无权访问tempColor,但是在哎此函数内部全可以访问其他两个环境中的所有变量。因为另外两个环境是它执行的父环境
JS中无块级作用域
在其他类C的语言中,由化括弧封闭起来的代码块都有自己的作用域。但是JS会根据条件定义变量
例如:
if(true){
var color = "blue";
}
alert(color);//"blue"
这里在if语句中定义了一个变量color,如果在C,C++,或者Java中,color会在if语句执行完毕之后销毁,但是在JS中,if语句中的变量声明会将变量添加到当前的执行环境中去(这里指的是全局环境),在使用for语句时尤其要牢记这一点:
for(var i = 0;i<10;i++){
doSomething(i);
}
alert(i);//10
再例如:
for(var i = 0;i<3;i++){
console.log(i);
}
var arr = [1,2,3,4];
function shuchu(){
console.log(arr[i]);//可以访问到i的值
}
shuchu()
声明变量:
使用var 声明的变量会自动添加到最近的环境中去,在函数内部,最近的环境就是环境内部