1.1什么是函数提升和变量的提升?

JS引擎在运行整个JS代码的过程中,分为俩步。

第一步是读取和解析JS代码,第二部是执行。

在引擎解析JS代码的时候,当解析器遇见变量声明(var 变量名)和函数声明

(function 函数名)的时候,会将这些声明提到各自作用域的最前面。

1.2 作用域

在ES6之前,JS是没有块级作用域的。只有2种作用域:

  • 1.全局作用域
  • 2.函数作用域

注:在其他语言中,{...}被称为代码块,所形成的作用域被称作块级作用域,如:

        if(...){
var a = 1;
}
for(var i = 0;i<5;i++){
var b = 1;
}
console.log(a);
console.log(b);
console.log(i);

如果以上俩例子有块级作用域的话,a,b,i是不能被访问到的,但是

在JS中是可以的(ES6之前),所以没有块级作用域。

2.1 变量提升

2.1.1 声明变量

首先我们声明变量是通过var关键字,如果不用var直接赋值的话会被解析器

当作是全局变量。但是切记,变量的提升只限于用var声明的变量,没通过

var声明的变量将不会被提升。看下边的例子:

    var a = 1;
console.log(a);// 1
// 输出的结果为1,没问题,因为代码在执行的时候是按顺序执行的。
// 解析的时候,经过变量提升后的结果如下:
var a;
a = 1;
console.log(a);// 1
    console.log(a);// undefined
var a = 1;
// 这次的结果输出为undefined,我们都知道,当一个变量声明了却未赋值的时候就会出现undefined,
// 但是一个变量没有声明的话,就会输出 a is not defined,先看本例经变量提升后的结果:
var a ;
console.log(a);// undefined
a = 1;
// 所以由此可见,变量的提升只会提升变量的声明,而不会提升变量的赋值。
    console.log(a);// a is not defined
a = 1;
// 当我们把var去掉的时候,结果变成了 a is not defined,很明显,没有var声明的变量,没有被提升至作用域的最前边,也就是变量提升只是对用var声明的变量而言的。
  1. 函数的内部也是如此
    (function(){
console.log(a);//undefined
var a = 1;
})()
提升结果如下:
(function(){
var a
console.log(a);//undefined
a = 1;
})()

2.1.2 所以暂时我们可以总结一下变量提升:

  1. 只有用var声明的变量才存在变量提升这一说法
  2. 变量提升只提升变量的声明,不会提升赋值这一部分;

3.1 函数提升

3.1.1函数的声明

函数的声明有俩种方式,一种为:

    function fn(){

    }
//另一种为:
var fn = function(){ }
// 首先的我们得知道函数属于引用类型,函数名实际上相当于一个指针,保存的是函数体所在的地址,所以函数也可以通过函数表达式var fn来声明,但是同为函数,他们的提升结果却是不同的。

3.1.2 函数式声明

    function fn(){
console.log('hello');
}
fn();// hello
// 结果输出为hello,这个不难理解,代码的顺序执行。函数提升后的结果还是这样。
    fn();// hello
function fn() {
console.log('hello');
}
// 执行结果还是hello,因为函数在解析代码的时候,同样,函数的声明被提到了作用域的最前边,如下:
function fn(){
console.log('hello');
}
fn();// hello
// 需要注意的是整个function fn(){...}均为函数的定义(声明)。
    var fn = function(){
console.log('hello');
}
fn();//hello // 用var声明的函数同变量一样,先把定义提升至最前边,如下:
var fn;
fn = function(){
console.log('hello');
}
fn();//hello
    fn();//fn is not a function
var fn = function(){
console.log('hello');
}
// 但是将用var声明的函数放在后边就不行了,因为这样声明的函数,提升后是下边这样的:
var fn;
fn();//fn is not a function
fn = function(){
console.log('hello');
}
// 同变量提升一样,提升的只是定义,并没有赋值。

4 综合运用

console.log(a);
function a() { //定义函数 }
console.log(a);
var a = 3; //变量
console.log(a); 运行结果如下:
function a() { }
function a() { }
3
    console.log(a);
var a = 3;
console.log(a);
function a() { }
console.log(a);

由此可见

俩次举例中,函数和变量是同名的,在代码未执行到变量赋值语句的时候,console打印出来的均为函数,变量赋值以后,打印的才是刚刚赋的值,所以由综合例子可以得出:当变量和函数同名时,函数的优先级高!

总结

由以上的例子不难看出变量提升和函数提升的特点,可以总结如下:

  1. 所有的声明都会提升到各自作用域的最顶上去。
  2. 只有用var声明的变量才存在变量提升这一说法
  3. 变量提升只提升变量的声明,不会提升赋值这一部分;
  4. 同一个变量只会声明一次,其他的会被忽略掉。
  5. 函数声明的优先级高于变量声明的优先级
  6. 所有变量的声明,在函数内部第一行代码开始执行的时候就已经完成。

最新文章

  1. 如何通过JS调用某段SQL语句
  2. JAVA 多线程随笔 (二) sleep, yield, join, wait 和notify
  3. centos6.5 redmine 安装
  4. android手机调试时不能打印Logcat日志信息
  5. wpf添加超链接
  6. 在VLFEAT中mat类型图片转换成constant float* 来进行vl_dsift_process
  7. 使用NBU进行oracle异机恢复
  8. C#窗体四边框阴影效果的实现
  9. 循环嵌套,while循环,穷举迭代循环
  10. Page 16 Exercises 1.2.3 -------Introduction to Software Testing (Paul Ammann and Jeff Offutt)
  11. Python【基础第二篇】
  12. java 中 ==和equals 的区别
  13. sql server 数据库基础学习心得 思维导图
  14. ios面试题整理
  15. python 间谍程序传输文件 socket编程
  16. 最佳实践:Windows Azure 网站 (WAWS)
  17. 201521123086《java程序设计》第7周
  18. 进程,线程,GIL,Python多线程,生产者消费者模型都是什么鬼
  19. BSGS(Baby Steps,Giant Steps)算法详解
  20. 启动aspx文件错误

热门文章

  1. Linux vi/vim使用
  2. win7 磁盘碎片整理
  3. Spring WebClient vs. RestTemplate
  4. vue 初始化table数据,数据闪现的问题
  5. 【Android】Error:Execution failed for task &#39;:app:lint&#39;
  6. Java编程思想之十七 容器深入研究
  7. 两份简单的logstash配置
  8. Button 使用详解
  9. LR有的JMeter也有之二“检查点”
  10. JVM系列(2)- jmap+mat实战内存溢出