变量提升(声)
- 在JS代码执行之前,浏览器要先过一遍代码,把其中 带 var 和 带 function 关键字内容提前声明 ;
- 带 var 是只声明(给个默认值 undefined) 不定义
- 带 function 是声明加定义
- 因为 用function 关键字声明的函数 ;在变量提升阶段已经附好值了,所以 我们可以在JS文件中的任意位置调用这个函数
- 变量提升 只会提升 = 号 左边的部分; 不会提升右边的部分
- var 一个变量, 相当于 给 window添加一个属性
- 带var 会进行变量提升 ,不带var 的没有变量提升
- 变量提升 是不看条件成立不成立的; 这个是针对var 来说的
- 针对 function 来说 ,在条件语句中的function声明;标准浏览器下是只声明,不定义的,在 IE低版本 是既声明 也 定义的
* var a = 12;
* let a = 12; // 不能重复声明 能重复定义
* let 没有变量提升的;
*
* const a = 12;声明常量用的 不能重复声明 也不能重复定义
* const 没有变量提升
// console.log(a,b);
// let c = 13;
var c;//声明
c = 14;//定义
var a = 12;
var a = 13;
var b = 13;
//let
let e = 13;
e=23;
// console.log(e);
// console.log(a,b);
// function sum() {
// console.log(1)
// }
// sum2();
// var sum2 = function sum3() {
// console.log(2)
// };
// sum2();
d = 2;
// console.log(d);
const aa = 14;
// aa = 13;
// console.log(f,g);
console.log(sum2,sum3);
if(1 > 2){
var f = 12;
function sum2() {
console.log(12)
}
}else {
var g = 14;
function sum3() {
console.log(13);
}
}
console.log(sum2,sum3);
// console.log(f,g);
作用域
- 堆内存:存储的对象键值对和函数的函数体
- 栈内存:存储基本数据类型 提供代码运行的环境
-
作用域: 属于栈内存
代码执行都会有一个运行环境;我们把这个运行环境成为作用域;
- 私有作用域 ----》函数执行会形成一个私有作用域;提供函数执行的环境
- 全局作用域 ----》 页面一打开就会形成一个全局作用域;这个作用域是提供整个JS执行环境的
- 私有变量 ----》 在私有作用域下声明的变量叫做私有变量 (通过 var声明; 形参)
- 全局变量 ----》 在全局作用域下声明的变量叫做全局变量(var ; a = 12)
- 作用域链 每一个私有作用域都会有他的上级作用域,他的上级作用跟他在哪定义的有关系
上级作用域
函数执行就会形成一个私有的作用域;那这个私有作用域的上级作用域 是谁?
跟这个函数在哪个作用域定义 有关系;在哪个作用域定义的,那么他的上级作用域就是谁
函数执行的一个过程
函数执行, 先开辟一个私有作用域
然后再进行变量提升 (var function 提前声明, 先形参赋值, 再变量提升)
代码从上到下 依次执行
// var foo=1;
// function bar(){
// // 不管条件是否成立 都要进行变量提升
// // 这时的 foo 属于私有变量 给的默认值是 undefined
// if(!foo){
// var foo=10;
// }
// // if(var i =0){
// //
// // }
// console.log(foo);
// }
// bar();
函数的上级作用域 只跟函数在哪个作用域定义的有关系
跟函数在那里执行 没有任何关系
var n=0;
function b(){
n++;
alert(n);
}
function a(){
var n=10;
b();
}
//函数的上级作用域 只跟函数在哪个作用域定义的有关系
//跟函数在那里执行 没有任何关系
b();
a();
alert(n);
扩展题
1.
var n =10;
function outer(){
var n =15;
function inner(){
function center(){
alert(n)
}
center()
}
inner();
}
outer();
结果输出是15;
第一步:
页面打开形成全局局作用域,全局作用域里面有var n=10 和 outer函数进行变量提升,然后代码自上而下执行n=10;outer函数执行形成一个私有作用域
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL1IDNyUTM1kTMwITMwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
形成私有作用域后,私有作用域里的var n和inner进行变量提升,给inner函数一个堆内存的地址,然后代码执行,n=15,inner函数执行,依次类推;
直接到center函数执行,到里面alert(n)执行,因为center函数里面没有n变量,没有传参,所以查找上一级作用域,他的上一级作用域跟他在哪定义有关系,也就是inner函数,inner里面没有n,一直查找上一级作用域到outer函数,里面有n=15,停止向上查找作用域;
2.
var n =10;
function a(){
var n =10;
function b(){
n++;
alert(n)
}
b();
}
a();
alert(n)
解析: 答案 : 11;0
全局作用域生成,var n=0,和function进行变量提升,给a这个函数一个内存地址;,然后函数自上而下执行,a函数执行,形成私有作用域,然后里面var a =10,进行变量提升,给b函数一个内存地址,然后b函数执行,,里面没有形参赋值和变量提升,n++,b函数里面没有n变量,从上一级作用域查找,上一级作用域是a函数,里面有var n=10;所以b函数执行,n++。alert(n)是11;然后a函数执行完毕,到最后面第二个alert(n),也就是最外面的这个执行,
调用全局作用域,n变量,等于0;
3.
var n =0;
function b(){
n++;
alert(n);
}
function a(){
var n=10;
b();
}
b();
a();
alert(n);
这个a函数执行里面的b()函数执行,b里面的n仍从b的上级作用域全局作用域查找n变量,并不是b函数在a函数里面执行,a函数就是b函数的上级作用域
函数的上级作用域 只跟函数在哪个作用域定义的有关系
跟函数在那里执行 没有任何关系
4.
f = function(){return true};
g = function(){return false};
(function (){
console.log(g);
if(g()&&[]==![]){
f= function f(){return false};
function g(){return true};
}
})();
alert(f());
alert(g())
输出一个undefined报错,
全局没有变量提升,然后代码自上而下执行,到function自执行函数执行形成私有作用域,私有作用域形成,里面g函数进行变量提升,只声明不定义,所以console.log(g)输出一个undefined,然后if里面判断执行,g不是一个函数,报错;