三,变量的作用域
根据变量作用范围不同,分类
局部变量
在函数内部声明的变量(必须使用var)
只能在函数内部访问它
可以在不同的函数中使用名称相同的局部变量
全局变量
在函数外声明的变量
网页的所有脚本和函数都能访问它
var x = 10; function f1(){ var y = 5; console.log(x); // 10 console.log(y); // 5 } f1(); console.log(x); // 10 console.log(y); // y is not defined
局部变量与全局变量的区别
区别 | 局部变量 | 全局变量 |
作用域 | 仅作用在函数中 | 作用在整个脚本 |
声明位置 | 函数中 | 使用之前的任何位置 |
生存期 | 在函数运行以后被删除 | 在页面关闭后被删除 |
3.1,隐式全局变量
如果变量声明时,没有使用关键字var,则被称为隐式全局变量
示例
var a1 = 1; //全局变量 a2 = 2; //隐式全局变量
如果在函数内部声明变量时,没有使用关键字var,则也是隐式全局变量
function f1(){ var num = 100; } f1(); console.log(num); // 函数会报错
function f1(){ num = 100; } f1(); console.log(num);
与解析:
1.会把全局变量的“声明”提前 2.提前声明函数,但是函数内部的代码是不执行的 局部变量:必须在函数内部使用var/let声明,如果不使用,则称为隐式全局变量 隐式全局变量:只有在执行后使用, 全局变量和局部变量可以重名,使用就近原则
四,作用域与块级作用域
作用域
是变量与函数的可访问范围
控制着变量与函数的可见性和生命周期
块级作用域
由花括号“ { } ”限定
所有的变量都定义在花括号内
变量从定义开始到花括号结束的范围内可以使用
使用场景
正常带有大括号的语句
条件语句
循环语句
函数
正常带有大括号的语句 { var num = 10; } console.log(num); // 10 // 条件语句 if(true){ var num = 20; } console.log(num); // 20 // 循环语句 for(var i=0;i<5; i++){ var num = 30; } console.log(num); // 30 // 函数 function f1(){ var num = 50; } f1(); console.log(num); // num is not defined
五,作用域链
Scope Chain
是JavaScript内部一种变量、函数查找机制
决定了变量和函数的作用范围
当执行函数时,先从函数内部寻找局部变量
如果内部找不到,则向创建函数的作用域寻找,依次向上
如果最终没有找到,通常会报错
var num = 10; // <script>里定义的变量,是0级作用域 function f1(){ var num = 20; // 1级作用域 function f2(){ var num = 30; // 2级作用域 function f3(){ var num = 50; // 3级作用域 console.log(num); } f3(); } f2(); } f1()
六,闭包
如何在函数外部读取函数内的局部变量呢?
闭包(closure)
能够读取其他函数内部变量的函数
是将函数内部和函数外部链接起来的桥梁
实现步骤
在一个函数的内部,再定义一个函数
把内部的函数作为返回值
特性
函数嵌套
内部函数可以访问外部函数的变量
参数和变量不会被回收
最典型的应用
实现回调函数
// 1.在函数内部定义一个函数 // 2. 把内部函数作为外部函数的返回值 // 原理:利用了内部函数可以调用外部函数的变量 function f1(){ var num = 20; function f2(){ alert(num); } return f2; } var result = f1(); result();
作用
可以读取函数内部的变量
让这些变量的值始终保存在内存中
缺点
在父函数外部,可以改变父函数内部变量的值
常驻内存,会增大内存使用量,使用不当很容易造成内存泄露