Javascipt变量提升、作用域

如果在牛客网刷题的小伙伴,你会发现很多代码执行的结果和你预想的不一致,首先看下面的一段代码

var a=10;
(function test(){
console.log(a)
var a=15;
console.log(a)
})();

上面一段代码,之前一直以为结果是10,15 实际执行结果为

undefined
15

看到结果很意外,问什么第一次打印结果为undefined,这里就要讲到变量提升,任何函数内部变量都会先提升,你可以理解为执行顺序为:

var a=10;
(function test(){
var a;
console.log(a)
a=15;
console.log(a)
})();

看到这个执行顺序是不是感觉很清晰了,变量提升之后,作用域发生了改变,下面我们就来讲讲作用域和变量提升

作用域:

javascript 在es6之前的版本只有全局作用域和函数作用域

全局作用域:在函数任何位置都能访问到,生命周期伴随着页面的生命周期,

函数作用域:是指在函数内部定义的变量和函数,只能在函数内部访问,函数执行之后,函数内部的变量和函数都会被销毁。

es6之后才引入块作用域同时利用let、const来处理var缺陷(变量提升)

一、变量提升:

如果变量声明在函数里面,则将变量声明提升到函数的开头;

如果变量声明是一个全局变量,则将变量声明提升到全局作用域的开头;

变量提升分为两步,第一步变量声明的提升,第二步变量的赋值;

案例1:全局变量提升

console.log(a); // 'undefined'
var a = 'csdn';
console.log(a); // csdn

实际运行时代码:

var a;  // 全局变量声明提升
console.log(a); // 'undefined'
a = 'csdn';
console.log(a); // csdn

 案例2:函数内变量提升

var a = 'global';
function fun() {
   console.log(a); // 'undefined'
   var a = 'local';
   console.log(a); // local
}
fun();
实际运行时代码:
var a ; // 全局变量声明提升
 a ='global';//声明后赋值
function fun() {
   var a; //函数内变量声明提升
   console.log(a); // 'undefined'
   a = 'local';//函数内赋值
   console.log(a); // local
}
fun();

 二、函数提升

函数的提升是直接将整个函数整体提升到作用域的最开始位置,相当于直接复制到开始;

函数声明只会提升函数声明,不提升函数表达式;

函数提升后会生成一个函数表达式;

案例1:函数声明式

console.log(fun1); // [Function: fun1]
fun1(); // fun1
function fun1() {
   console.log('fun1');
}
实际运行时代码
var fun1=function(){
console.log('fun1');
}
console.log(fun1); // [Function: fun1]
fun1(); // fun1
案例2:函数表达式,保持原来不变
console.log(fun2); // undefined
fun2(); // TypeError: fun2 is not a function
var fun2 = function () {
   console.log('fun2');
};
实际运行时代码:
console.log(fun2); // undefined
fun2(); // TypeError: fun2 is not a function
var fun2 = function () {
   console.log('fun2');
};

三、提升顺序

函数声明提升比变量提升优先级要高,且不会被变量声明覆盖,但会被变量赋值时覆盖;

a() > a

案例:

console.log(a); // f a() {console.log(10)}
console.log(a()); //  undefined
var a = 3;
function a() {
   console.log(10); //10
}
console.log(a); //3
a = 6;
console.log(a()); //a is not a function;

 实际执行结果

var a = function(){  // 函数提升
console.log(10);
}
var a;   // 变量提升
console.log(a); // f a() {console.log(10)}
console.log(a()); //  undefined
a = 3;
console.log(a); //3
a = 6;
console.log(a()); //a is not a function;

 

变量提升的意义

我们知道在js运行时需要分两步,一步是解析阶段,一步是执行阶段;

1、容错性更好:

 JS作为一个脚本语言,在代码解析阶段,对js进行预编译,就可以发现一些语法上的错误,及时抛出错误,容错性更好;

2、提高性能:

在解析阶段函数的语法检查与预编译,操作只执行一次,目的是为了提升性能,若没有语法解析和预编译,那每次代码执行都要进行预编译和为函数分配空间,这样将要浪费很多时间,占用很多空间,这就是为什么javascript运行速度很快,而Java执行速度很慢,因为每次运行的时候要先预编译。

块级作用域:var缺陷以及为什么要引入let和const | 浏览器工作原理与实践

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值