作用域
变量的作用域:变量在一个范围内是有效的,这个范围就是变量的作用域。
在此作用域内,可以使用、改变变量。
全局变量:在函数外部定义的变量、在函数内部没有var声明的变量。
局部变量:在函数内部定义的变量。
作用域链
作用域中查询变量时,从内到外依次查找,找到停止,没找到就一直查找到最外层。
JavaScript预解析(预编译、声明提前)
浏览器中有解析js代码的程序===>js引擎
①先进行预编译,把js代码转换成机器码。
JavaScript代码在执行之前,会将所有变量、函数声明提升到所在作用域最前面初始化为undefined。
(根据var、function去找,然后放入仓库中,要用的时候去找)
②解释执行,由上至下,逐行执行js代码
每遇到一个新的作用域,都会执行这两步。
例1:
alert(a); //undefined
alert(b); //undefined
alert(c); //undefined
alert(fn1); //弹出整个代码块
var a = 1;
alert(a); //赋值将undefined覆盖,弹出1
var b = 2;
var c = 3;
function fn1() {
alert("fn1");
}
例2:
alert(a); //function a() {alert("fn1")}
var a = 10;
alert(a); //10
function a() {
alert("fn1");
}
a(); //报错
执行步骤:
1、先将变量和函数找到,放进仓库。
a = undefined
a = function a() {alert(“fn1”)}
变量和函数同名,保留函数。
函数同名,保留后者。
2、逐行执行代码。
alert(a) ===> function a() {alert(“fn1”)}
a = 10 ===> 改变仓库中的值
alert(a) ===> 10
a() ===> a再调用时已经变成了10,报错
例3:
var a = 10;
function fn(){
alert(a); //undefined
var a = 20;
}
fn();
alert(a); //10
执行步骤:
1、先将变量和函数找到,放进仓库。
a = undefined
fn = function fn() {…}
2、逐行执行代码。
a = 10
fn() 每个函数都是一个作用域快
1 找变量、函数
a = undefined
2 逐行执行
alert(a) ===> undefined
a = 20
alert(a) ===> 10
例4:
function Foo() {
// 函数表达式 没有用var定义 全局变量
getName = function () {
alert(1);
};
return this;
}
// 静态方法
Foo.getName = function () {
alert(2);
}
// 公共方法
Foo.prototype.getName = function () {
alert(3)
}
// 函数表达式
var getName = function () {
alert(4);
}
// 函数声明
function getName() {
alert(5);
}
console.log(Foo.getName()) //undefined,因为没有return
getName(); //弹出4(变量提升)
Foo().getName(); //弹出1(this指向window),全局的getName被Foo()中的getName覆盖
new Foo.getName(); //弹出2,相当于new function(){ alert(2)}