目录
一.
概念:
定义了变量之后,变量会在一定范围里面起作用,这个起作用的范围就是作用域。script标签是最大的作用域,定义在这里的变量称为全局变量; 每个作用域定义的变量只能供当前作用域和下属作用域调用。
作用域的作用:
是为了提高程序的可靠性,更重要的是减少命名冲突。
二.
1. 变量声名
概念:
es6之后,JavaScript的声名发生了翻天覆地的变化,在es6之前都是采用var声明变量,es6不仅增加了 let 和const两个关键字,而且还让这两个关键字压倒性的超越了var 成为首选。
尝试使用var定义变量:
var name = "haoha";
//等价于
name = "haoha";
var name;
console.log(name);
//验证变量提升
console.log(name); //undefined... 变量提升
var name = "haoha";
//总结;var 声明的变量会被拿到函数或全局作用域的顶部,位于作用域中所以代码之前。这个现象叫做"提升" 提升可以让同一作用域中的代码不必考虑是否已经声明就可以直接使用
2. 变量作用域的分类
概念:
根据作用域(上下文)的不同,我们把变量分为全局变量和局部变量。
var name = "haoha"; //在全局作用域下的定义的变量
console.log(name);
function fn(){
var myName = "ztf"; //在局部作用域中定义的变量 只能在函数内部访问
console.log(name);
}
console.log(myName); //访问不了 报错 myName is not defined
//全局变量的另一种表示方式
function fn(){
myName = "ztf";
console.log(myName);
}
console.log(myName); //ztf 可以正常访问, 在函数内部没有声明变量直接赋值的 也被认为是一个全局变量
//总结 全局变量和局部变量的区别
//全局变量:在全局都可以使用,要等到浏览器关闭才会被销毁
//局部变量:只能在函数内部使用,函数执行完 里面的变量也会销毁
3. 作用域链
概念:
当我们在某处使用某个变量时,会先从当前作用域查找,如果有则使用,如果没有,则往上一层作用域查找,以此类推,如果直到全局作用域还没找到,就会报错,这就是作用域链。
//作用域初探
var color = "red";
function fn(){ //外部函数
var color = "green";
function fun(){ //内部函数
console.log(color); //首先在fun作用域中查找发现没有,然后沿作用域链向上查找 查找到fun 内部有一个color;
}
fun();
}
fn(); // green
案例:
function f1(){
var num = 1;
function f2(){
var num = 0;
console.log(num); //在自身的作用域中能够找到num = 0,停止向上查找
}
f2();
}
var num = 2;
f1(); // 0
4. 变量和函数预解析:
console.log(name) //undefined
var name = "小白";
//函数预解析
//sum(): 也可以调用
function sum(){
console.log("这是一个函数");
}
//sum(); 可以调用
//函数内部的预解析
function fn(){
console.log(myName);
var myName = "小白";
}
fn();
//函数表达式
fun(); //报错 fun is not a function
var fun = function(){
console.log("这是一个函数表达式");
}
/*总结;
js引擎执行循序:1.预解析 2.执行代码
预解析过程:js引擎会先创建一个执行上下文环境,然后收集var关键字,函数(function),参数
)
变量:var 声明的变量会被拿到函数或全局作用域的顶部,位于作用域中所以代码之前。这个现象叫做"提升" 提升可以让同一作用域中的代码不必考虑是否已经声明就可以直接使用
函数:
*/
//实际用途:
//变量重名覆盖问题
var name = "小白";
var name = "小黑";
console.log(name);
//局部作用域 区分作用域的范围
var name = "小白";
function getName(){
var name = "小黑";
}
console.log(name);
//作用:是为了提高程序的可靠性,更重要的是减少命名冲突
预解析案例:
案例1:
console.log( func );
var func = 123;
console.log( func );
function func() {
console.log( 'Hello js' );
}
//分析
// 预解析结束,开始执行代码
// 第一个console.log(func)此时为函数体,打印出函数体
// 第二个conole.log(func)已经赋值,覆盖了函数体,打印123
案例2:
function func1 ( num ) {
console.log( num );
var num = 456;
console.log( num );
}
var num = 123;
func1( num );
//123
//456
案例3:
var num = 123;
function f1 () {
console.log( num );
}
function f2 () {
var num = 456;
f1();
}
f2();
console.log( num );
//123,123
案例4:
function fn(){
var a = b = c = 9; //相当于 var a = 9;b=9;c=9; 所以 b,c 相当于全局变量
console.log(a);
console.log(b);
console.log(c);
}
fn();
console.log(c);
console.log(b);
console.log(a);