前言
了解掌握作用域能够有效的帮助我们在调试JavaScript遇到问题时,很快的找到浏览器在运行到哪一步出现了问题。
作用域的定义
w3c中对作用域的定义:
JavaScript 作用域
在 JavaScript 中, 对象和函数同样也是变量。
在 JavaScript 中, 作用域为可访问变量,对象,函数的集合。
JavaScript 函数作用域: 作用域在函数内修改。
作用域的分类
1.变量在函数内声明,变量为局部作用域。【注:局部变量只能在函数内部访问,函数执行完后局部变量会自动销毁。】
2.变量在函数外定义,即为全局变量。全局变量有全局作用域。
JS在浏览器中解析步骤:
1) 预解析
- 浏览器在解析JavaScript时,并不是一上来就直接执行运算或函数,而是先进行“预解析”。
- 在“预解析”中,浏览器先会找一些具有标示性的例如:var 、function表达式 、参数(参数相当于局部变量),解析到储存器中。
【注意:①所有的变量,在正式运行代码前,都提前赋了undefined值;②所有的函数,在正式运行代码前,都是整个函数块;③如果有重名的,只会保留一个,变量与函数重名了,保留函数。】
2) 逐行解读代码
遇到表达式:= + - * / % ++ – ! 参数等时,解读代码!【表达式能改变预解析的值】
规则
- 当局部作用域中变量完整时,即函数会在局部环境中现在自己的变量对象中搜索变量名和函数名,这时可以进行“预解析”,不向上从全局或父级中找变量,不改变父级内容。
- 当索索不到则搜索时,通过作用域链访问上级,并且可以改变全局内容。
- 内部环境可以通过作用域链访问所有外部环境,但是外部环境不能访问内部环境中的任何变量和函数,即可向上访问,不可向下访问。
- 在JavaScript中没有块级作用域,因此,if语句中的变量声明会将变量添加到当前的执行环境中,for语句在执行循环结束后,也依旧会存在与循环外部执行的环境中。【因为火狐浏览器的特殊原因,尽量不要在if和for里定义变量和函数表达式】
以下是从老师那里找来的几个经典例子:
alert(a); // function a (){ alert(4); }
var a = 1;
alert(a); // 1
function a (){ alert(2); }
alert(a); // 1
var a = 3;
alert(a); // 3
function a (){ alert(4); }
alert(a); // 3
alert( typeof a );
// a(); // 报错
var a = 1;
function fn1(){
alert(a); // undefined
var a = 2;
}
fn1();
alert(a); // 1
var a = 1;
function fn1(){
alert(a); // 1
a = 2;
}
fn1();
alert(a); // 2
var a = 1;
function fn1(a){
alert(a); // undefined
a = 2;
}
fn1();
alert(a); // 1
var a = 1;
function fn1(a){
alert(a); // 1
a = 2;
}
fn1(a);
alert(a); // 1
全局想要获取局部(函数)中的值:
var str = '';
function fn1(){
var a = '大鸡腿~';
str = a;
}
fn1();
// alert( str );
function fn2(){
var a = '9999999克拉钻石23456789';
fn3(a);
}
fn2();
function fn3(a){
alert(a);
}
在今天的学习之后,更能理解浏览器运算时的先后顺序,对于以后在写JavaScript代码时测试,多了一种审查方式。