精华内容
下载资源
问答
  • 浅谈JS变量提升
    万次阅读 多人点赞
    2018-07-07 16:42:35

    1. 变量提升

        ES6之前我们一般使用var来声明变量,提升简单来说就是把我们所写的类似于var a = 123;这样的代码,声明提升到它所在作用域的顶端去执行,到我们代码所在的位置来赋值。

    function test () {
        console.log(a);  //undefined
        var a = 123; 
    };
    test();

    上述代码a的结果是undefined,它的实际执行顺序如下:

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

    再看一个:

    a = 1;
    var a;
    console.log(a); //1

    第一眼看到的时候是不是会认为undefined, 记住声明会提升到作用域顶端。

    下面来看一道经典面试题:

    console.log(v1);
    var v1 = 100;
    function foo() {
        console.log(v1);
        var v1 = 200;
        console.log(v1);
    }
    foo();
    console.log(v1);

    输出的结果:

    //undefined
    //undefined
    //200
    //100

    2. 函数提升

        javascript中不仅仅是变量声明有提升的现象,函数的声明也是一样;具名函数的声明有两种方式:

        1. 函数声明式    2. 函数字面量式

    //函数声明式
    function bar () {}
    //函数字面量式 
    var foo = function () {}

    函数字面量式的声明合变量提升的结果是一样的,函数只是一个具体的值;

    但是函数声明式的提升现象和变量提升略有不同

    console.log(bar);
    function bar () {
      console.log(1);
    }
    //打印结果:ƒ bar () {
    //  console.log(1);
    //}

    执行顺序相当于:

    function bar () {
      console.log(1);
    }
    console.log(bar);

    函数提升是整个代码块提升到它所在的作用域的最开始执行

    思考下面的问题(看明白函数声明式提升下面的问题大概可以理解为什么输出1而不是2了吧):

    foo(); //1
    
    var foo;
    
    function foo () {
        console.log(1);
    }
    
    foo = function () {
        console.log(2);
    }

    这就是函数优先规则。

    下面这段代码,在低版本的浏览器中,函数提升不会被条件判断所控制,输出2;但是在高版本的浏览器中会报错,所以应该尽可能避免在块内部声明函数

    foo(); //低版本:2  //高版本: Uncaught TypeError: foo is not a function
    
    var a = true;
    
    if(a){
        function foo () { console.log(1); }
    }else{
        function foo () { console.log(2); }
    }

    小结:

        我们习惯将var a = 2;看做是一个声明,而实际上javascript引擎并不这么认为。它将var a和a = 2看做是两个单独的声明,第一个是编译阶段的任务,而第二个则是执行阶段的任务。

        这意味着无论作用域中的声明出现在什么地方,都将在代码本身被执行前首先进行处理,可以将这个过程形象地想象成所有的声明(变量和函数)都会被“移动”到各自作用域的最顶端,这个过程被称为提升。

    本文参考《你不知道的javascript》上卷

    更多相关内容
  • 主要介绍了JS变量提升及函数提升实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 本文实例讲述了JS变量提升。分享给大家供大家参考,具体如下: 该篇介绍什么是变量提升,写给像我一样的JS新手看的 简单来说变量提升就是 JS会把var变量的声明自动提升到作用域的顶部,即使你不想这样 一个例子: (局部...
  • 下面小编就为大家带来一篇最通俗易懂的javascript变量提升详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • JavaScript变量提升详解

    2021-08-16 19:35:27
    js中我们用var声明的变量是存在变量提升的。换句话说,我们js的解释器在解释js代码的时候,会优先把所有的变量声明提到前面。 示例代码 var的变量提升 下面我演示的就是一个简单的变量提升的问题。 js源代码 ...

    变量提升

    在js中我们用var声明的变量是存在变量提升的。换句话说,我们js的解释器在解释js代码的时候,会优先把所有的变量声明提到前面。

    示例代码

    var的变量提升

    下面我演示的就是一个简单的变量提升的问题。

    js源代码

    console.log(a)
    var a=1
    console.log(a)
    

    js解释器编译的顺序:

    //js编译时会把所有的变量声明提前
    var a;
    console.log(a)//显示undefiend,因为此时a没有赋值不知道数据类型
    a=1//赋值操作不提前,只是var a的声明提前了
    console.log(a)//输出a
    

    这里理解的要点是,js只是把变量的声明提前了。但是赋值并没有提前。var a=1其实是两行代码的简写,var a;a=1

    function变量赋值提升

    接下来这个问题可是经典的面试题

    function foo(a){
        console.log(a)
        var a=2
        function a(){
            
        }
        console.log(a)
    }
    foo(10)
    

    请问两次的console.log分别打印出什么呢?

    想要搞清楚这个问题,我们需要理解变量提升的优先级。
    其实在JS中,被变量提升的不仅仅有var还有我们的function,而且function提升变量的优先级要比var要高一些,而且这个函数变量提升还是变量和赋值同时提升!!!

    所以上面这段代码在js解释器下是按照这样的顺序解释的

    function foo(a){
        //function a变量提升,并赋值function
        var a=function (){
            
        }
        console.log(a)
        a=2
        console.log(a)
    }
    foo(10)
    

    虽然我们调用foo函数时候传递了一个10进去,但是根据js的作用域链规则,js会优先在最小的作用域依次,向上、向外去寻找声明的变量。显然这个时候我在外面传的10就没有作用了,因为js在向上找的同时在{}里面找到了变量a的声明,也就是var a=function(),就没有必要向外找传递进来的10了

    所以第一个打印语句打印的是函数本体,第二个打印的是2

    理解上面代码的要点是理解function声明函数其实是变量和赋值同时提升,这里和我们的var是不一样的,var仅仅是声明提升,它的赋值不会提升,所以才有可能打印出undefined(undefined就是声明了但是却没有赋值的意思)

    局部变量的偷偷赋值

    我们看下下面案例的输出

    function foo(a) {
        var a
        console.log(a)
    }
    
    foo(10)
    

    输出结果是10

    奇怪了这是为什么呢?a我们没有赋值呀,根据作用域链规则,应该是undefined呀。为什么传递进去的10,却打印出来了。

    其实这里的底层是这样的

    //在括号外部a接收了传递的10
    function foo(var a=10) {
    	//你自己重复声明变量
        var a
        console.log(a)
    }
    
    foo(10)
    

    我们在console.log(a)时候,js沿着作用域链在括号内寻找,找到了a,发现是undefined,但是js不甘心,继续沿着作用域链向上检索,终于搜寻到外面的形参声明赋值,然后输出10
    也就是说作用域链向上查找不是查到声明就完的,如果js发现它是undefined的话还会继续向上找

    我们再来一道题练习一下作用域链

    var a=10
    var a=2
    {
        var a
        console.log(a)
    }
    

    输出2,不是undifined,js找到undifined是不会甘心的,会继续向上找不是undifined的数值,找到了一个不是undifined就不继续找了

    再来看一个有趣的事情

    function foo(a){
        console.log(a)
        var a=2
        console.log(a)
    }
    foo(10)
    

    这个我们来看js编译之后的执行顺序

    //形参接收a=10 这里写var其实是有语法错误的,我这样写是为了让大家理解
    function foo(var a=10){
        console.log(a)
        a=2
        console.log(a)
    }
    foo(10)
    

    显然输出10和2

    箭头函数和function不一样

    function foo(a) {
        console.log(a)
        a = () => {
    
        }
        var a = 2
        console.log(a)
    }
    
    foo(10)
    

    输出什么呢?

    我们来分析一下js编译之后的执行顺序

    //局部变量声明并接收参数赋值
    function foo(var a=10) {
        var a
        console.log(a)
        a = () => {
    
        }
        // var已经声明提升了
        a = 2
        console.log(a)
    }
    
    foo(10)
    

    输出10和2

    这里注意的是我们的箭头函数和function是不一样的,上面说我们的function是变量声明提升,赋值也会提升,但是我们的箭头函数仅仅只会变量提升而已,因为()=>function关键字是不一样的,function是声明函数的关键字,()=>只是一个赋值的右值而已

    回过头来再看这个例子

    function foo(a) {
        console.log(a)
        function a (){
    
        }
        var a = 2
        console.log(a)
    }
    
    foo(10)
    

    它输出的是function()和2

    js编译后的执行顺序如下

    //接收形参的传值
    function foo(var a=10) {
        var a = function (){
        
        }
        console.log(a)
        var a = 2
        console.log(a)
    }
    
    foo(10)
    

    好了,相信通过我的讲解,大家应该对变量提升有了新的认识了。我们下次再见,see you!

    展开全文
  • js变量提升

    2022-01-24 12:14:00
    js变量提升 堆栈内存 以及 基本&引用数据类型 基本数据类型&引用数据类型 浏览器加载我们js时候,首先会形成一个全局作用域window提供一个代码自上而下执行的环境; 引用类型会在作用域外 新开辟一...

    js变量提升

    堆栈内存 以及 基本&引用数据类型

    基本数据类型&引用数据类型

    浏览器加载我们js时候,首先会形成一个全局作用域window提供一个代码自上而下执行的环境;

    1. 引用类型会在作用域外 新开辟一块内存空间(有一个16进制地址),键值对依次存储到这个内存中;基本数据类型是直接在作用域开了一个位置就存了。

    1. 想让代码执行就得有一个执行的环境,所以函数执行首先都会形成一个私有的作用域。

    作用域:

    1. 提供代码自上而下执行的环境

    2. 存储基本数据类型,所有基本数据类型都是直接在该作用域开辟一个位置

    栈内存:即作用域

    堆内存:存储引用数据类型

    释放内存,让其不被占用,arr=null,

    变量提升机制

    在代码自上而下执行之前,浏览器会把带var或者function关键字的进行“声明”或“定义”,这就叫变量提升

    变量提升只发生在当前作用域

    私有作用域的变量提升和全局基本一致。私有作用域下的这些变量也就是私有变量,那我们就把保护私有作用域下的私有变量叫做闭包。

    带var和不带var

    全局的var变量和window属性存在映射关系

    不加var:添加了window的一个属性

    私有作用域

    带var:私有变量,跟外界没有关系

    不带var:就会向上级作用域查找,“作用域链”机制

    console.log(a,b); // undefined undefined
    var a = 12,b=12;
    
    function fn(){
        console.log(a,b); // undefined 12
        
        var a=b=13;
        console.log(a,b) // 13 13
    
    }
    fn();
    console.log(a,b); // 12 13
    

    function fn(){
        b=13;
        console.log(b) // 13
    
    }
    fn();
    console.log(b) // 13
    console.log(window.b) // 13
    

    提升的一些细节问题

    函数表达式和普通函数的区别

    普通函数:用function关键词来处理的

    函数表达式:只对函数左边进行变量提升

    console.log(fn);
    fn() // Uncaught TypeError: fn is not a function
    sum()
    
    var fn=function(){
        console.log(1)
    }
    function sum(){
        console.log(2)
    }
    
    

    条件判断下的变量提升

    当前作用域下,不管条件是否成立,都要进行变量提升

    console.log(a) // undefined
    if(1===2){
        var a = 2;
    }
    console.log(a); // undefined
    // 另一种情况
    console.log(a)
    if('a' in window){
        var a = 100;
    }
    console.log(a);
    
    

    function的一道题

    • 全局下没有变量提升(自执行没有名字所以也没有变量提升)。

    window.f = ...

    window.g = ...

    • 自执行函数部分:

    创建一个函数并且把它执行了。只要是函数执行,肯定会形成一个私有作用域。

    变量提升:带function的也只剩声明了g,但没有定义。私有作用域中声明一个变量是私有的,跟全局作用域是没有关系的。

    • [] -> []==false -> 0==0

    f = function(){ return true; };
    g = function(){ return false; };
    (function(){
        console.log('---');
        console.log(window.g);
        function g(){ return true; };
        if(g() && [] == ![]){
            console.log('panduan');
            f = function(){ return false; }
            function g(){ return true; };
        }
    })();
    console.log(f());
    console.log(g());
    
    

    这里还有块级作用域

    console.log(fn);
    // if(1===2) 那么结果又不一样 undefined
    if(1===1){
        console.log(fn);
        function fn(){
            console.log('ok');
        }
    }
    console.log(fn);
    

    但是这里又不是完整的块级作用域,因为这个fn还是全局的。

    重名问题的处理

    重名时会重新赋值不会重新声明

    fn(); // 4
    function fn(){ console.log(1) };
    fn(); // 4
    function fn(){ console.log(2) };
    fn(); // 4
    var fn = 100;
    fn(); // Uncaught TypeError: fn is not a function
    function fn(){ console.log(3) };
    fn(); // Uncaught TypeError: fn is not a function
    function fn(){ console.log(4) };
    fn();
    

    题外话

    let不存在变量提升

    let/const不存在变量提升。

    let a=6;
    console.log(a); // 6
    console.log(window.a); // undefined 不存在映射机制的
    

    语法检测:

    es6机制下,代码执行之前首先会做语法检测。

    1. 重复定义的会报错

    2. 并且它说,这些定义的变量在正式定义之前是不能使用的。

    // 这个例子很好
    // 全局 a,b,fn
    // fn执行形成一个私有作用域:let a,所以用a只能用在创建a的后面;b不是let,这里没有出现b,往上级去找
    let a=10,b=10;
    let fn=function(){
        // console.log(a,b);
        let a = b=20;
        console.log(a,b);
    }
    fn();
    console.log(a,b);
    

    a=3;
    let a=8;
    console.log(a);
    

    暂时性死区

    总结:

    首先先形成一个栈内存全局作用域,或私有作用域私有栈内存,在私有作用域下也会先验证它是不是私有变量,如果是的话就是自己的,如果不是则向上级作用域查找。

    代码执行之前会做很多事情:

    老规范会对变量进行提前声明或者定义,则按照变量提升机制走,新规范重复检测机制。

    let 会形成一个块级私有作用域,同上面函数作用域一样,在定义之前不能使用。

    // 题目
    var a=12;
    if(true){
        console.log(a); // 同理,这里使用也报错
        let a=13;
        console.log(a);
    }
    console.log(a);
    

    // 这是typeof的一个bug
    console.log(typeof a); // undefined
    
    

    javascript 暂时性死区_Novice-XiaoSong的博客-CSDN博客_js暂时性死区

    展开全文
  • JavaScript 变量提升

    2021-01-19 21:26:12
    JavaScript 变量提升 JavaScript 中,函数及变量的声明都将被提升到函数的最顶部。 JavaScript 中,变量可以在使用后声明,也就是变量可以先使用再声明。 以下两个实例将获得相同的结果: 实例 1 x = 5; // 变量 x...
  • 本篇文章给大家详细分析了javascript变量提升和闭包的相关知识点,对此有兴趣的朋友可以参考下。
  • JS变量提升

    千次阅读 2019-02-25 18:18:28
    变量提升(Hoisting)是人们对JavaScript执行上下文工作方式的一种认识,并不是官方给出的改变。从字面上理解,变量提升的意思是变量和函数的声明会在物理层移动到作用域的最前面,虽然这样理解并不准确,效果是相同的...

    什么是变量提升?

    变量提升(Hoisting)是人们对JavaScript执行上下文工作方式的一种认识,并不是官方给出的改变。从字面上理解,变量提升的意思是变量和函数的声明会在物理层移动到作用域的最前面,虽然这样理解并不准确,效果是相同的。变量提升实际的实现方式是JavaScript的变量和函数的声明会在编译阶段放入内存。这意味着使用者在正式声明一个函数或者变量之前就能够使用它。

    要搞清楚变量提升的实现,首先我们要明确以下2点:

    • javascript代码并不是一行一行往下执行的.
    • javascript执行分为2个步骤: 
    1. 编译(词法解释/预解释)
    2. 执行

    变量提升帮助理解 

    console.log(a);
    var a = 'ghostwu';

    对于上面的代码这个例子,第一行代码,你可能认为报错, 因为在输出a之前,没有定义a变量, 但是正确的结果是undefined.。根据上面js执行代码的解释,结合实际的代码,当我们碰到 var a = "ghostwu" 定义一个变量的时候, 其实js把这句话看成是2个阶段的事,  var a 发生在编译阶段, a = 'ghostwu'发生在执行阶段. 然后 var a会被提升到当前作用域的最前面,  a = 'ghostwu'留在原地等待执行阶段,所以看下面的案例:

    1 a = 'ghostwu';
    2 var a;
    3 console.log( a );
    4 
    5 //上面这段代码经过编译之后,变成下面这样
    6 
    7 var a;  //被提升到当前作用域的最前面
    8 a = 'ghostwu'; //留在原地,等待执行
    9 console.log( a ); //输出ghostwu
    
    
    
    10  console.log( a ); 
    12   var a = 'ghostwu';
    13 
    14   //上面这段代码,经过编译之后,变成下面这样
    15 
    16   var a;
    17   console.log( a );//输出undefined,而不会报错
    18   a = 'ghostwu';

    函数声明提升 

    在讲解函数声明提升之前,我们先来了解函数的常见的两种定义方式

    1         //函数声明, 形如:
    2         function show(){
    3             console.log( '函数声明方式' );
    4         }
    5 
    6         //函数表达式, 形如:
    7         var show = function(){
    8             console.log( '表达式方式' );
    9         }

    因为函数表达式和函数的声明,在编译阶段,会产生不同的解释效果,所以函数的声明会被提升,案例见下面代码:

    1         show();
    2         function show(){
    3             console.log( a );
    4             var a = 'ghostwu';
    5         }
    
    
    //函数声明会被提升,所以上面的代码经过编译之后,就变成下面这样
    
    6    function show(){    //函数声明被提升到 当前作用域的最前面
    7    var a;    
         //var声明被提升到当前作用域的最前面, 注意,他不会提升到函数的外面, 因为当前的作用域是在函数中
    8    console.log( a );
    9    a = 'ghostwu';
    10   }
    11   show();//输出undefined
    

    但是函数表达式是不会被提升的,看下面的例子:

    1 show(); //报错,show is not a function
     2 var show = function(){
     3  console.log( 'ghostwu' );
     4 }
     5 //对于上面这段表达式代码,经过编译之后:
     6 var show;
     7 show();  //执行之后就是 undefined(), 所以在表达式定义之前,调用函数报错了
     8 show = function(){
     9   console.log( 'ghostwu' );  
    10 }
    
    
    
    

    但是看下面的案例:

    1         show(); //你好
    2         var show;
    3         function show(){
    4             console.log( '你好' );
    5         }
    6         show = function(){
    7             console.log( 'hello' );
    8         }

    上面的代码为什么会输出“你好”,因为当出现同名的函数声明,变量声明的时候, 函数声明会被优先提升,变量声明会被忽略。 所以经过编译之后,就变成: 

    1         function show(){
    2             console.log( '你好' );
    3         }
    4         show(); //你好
    5         show = function(){
    6             console.log( 'hello' );
    7         }
    8         show();//如果这里在调用一次,就是hello, 因为show函数体在执行阶段被重新赋值了 

     但是如果有同名的函数声明,后面的会覆盖前面的,如下代码:

    
     1         show(); //how are you
     2         var show;
     3         function show(){
     4             console.log( 'hello' );
     5         }    
     6         show = function(){
     7             console.log( '你好' );
     8         }
     9         function show(){
    10             console.log( 'how are you!' );
    11         }  
    
    
    12        //上面的代码经过编译之后,变成如下形式:
    13         function show(){
    14             console.log( 'how are you!' );
    15         }
    16         show(); //how are you
    17         show = function(){
    18             console.log( '你好' );
    19         }
    20         show(); //如果在这里再执行一次,结果:你好

    注:

    1. 变量提升只是提升变量的声明,并不会把赋值也提升上来。
    2. 正因为有变量提升这回事,所以为了避免变量提升带来的不好的影响,我们最好在定义变量时,使用let而不是var。 

     

     

     

     

    展开全文
  • 主要介绍了JavaScript变量提升和严格模式,结合实例形式分析了javascript变量提升和严格模式的原理及相关操作注意事项,需要的朋友可以参考下
  • js变量提升详解

    2022-03-29 08:38:13
    js变量提升和函数提升详解
  • 什么是 js 变量提升 (Javascript Hoisting)

    千次阅读 2019-02-20 10:06:00
    Javascript是一门容易遭人误解的语言,但是它的强大毋庸置疑。...今天想通过自己的理解来对Javascript Hoisting(国内一般翻译为 变量提升)做一个阐述:  在解释Javascript Hoisting之前,先看一下几段代码: ...
  • JavaScript变量提升

    千次阅读 2021-11-20 13:05:57
    Javascript中执行上下文 (特别是创建和执行阶段)工作方式的一种认识,在ES6之前是找不到变量提升这个词的 “变量提升”意味着变量和函数的声明会在物理层面移动到代码的最前面,但实际上变量和函数声明在代码里的...
  • 文章目录变量提升执行上下文全局执行上下文函数执行上下文执行上下文栈作用域例题举个栗子 执行上下文栈:举个栗子 变量提升+执行上下文栈:举个栗子 预处理顺序举个栗子 预处理举个栗子 顺序执行举个栗子 作用域举...
  • 1.变量提升和函数提升 1.变量声明提升 *通过var定义(声明)的变量,在定义语句之前就可以访问到 *值:undefined 2.函数声明提升 *通过function声明的函数,在之前就可以直接调用 *值:函数定义(对象) 3.先执行变量...
  • 一、引入 在了解这个知识点之前,我们先来看看下面的代码,控制台都会输出什么 1 2 3 4 5 6 7 8 var foo = 1;...小炉:不不不,你并不知道变量提升和函数提升,请看下面正确的代码执行过程 1 2 3 4 5 6 7 8 9
  • 直接上代码例子1: console.log(a); 输出结果是 报错。   再看例子2: console.log(a);...此处例2的变量a的定义就是被提升到最前面,效果和例3相同。   接下来看下经典的函数声明, var tes...
  • js变量提升深入理解

    2020-10-21 12:48:44
    下面小编就为大家带来一篇js变量提升深入理解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • JavaScript变量提升

    2020-06-17 12:53:56
    2、变量提升 变量声明 console.log(a);//输出undefined var a = 10; console.log(a);//上面给a赋值的语句执行完毕,所以输出10 3、函数提升 常见的函数定义的方式由两种:函数声明和函数表达式 //函数表达式 var fn...
  • Javascript变量提升

    2022-01-14 15:15:08
    Javascript变量提升
  • JS变量提升和函数提升的顺序

    千次阅读 多人点赞 2020-10-19 23:25:36
    今天笔试时碰到考察变量提升与函数提升顺序的一道题目,之前只知道var定义的变量会有变量提升以及函数声明也会提升,但没有深入研究他们的顺序以及详细过程。事后查阅资料加上自己的验证,得出了自己对于它们顺序的...
  • 主要介绍了详解javascript 变量提升(Hoisting),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • js变量提升顺序

    2021-12-19 17:55:53
    js编译时会先进行变量的变量提升,再进行方法的变量提升,最终,方法的变量提升会覆盖变量的变量提升
  • 第一篇文章中提到了变量的提升,所以今天就来介绍一下变量提升和函数提升。这个知识点可谓是老生常谈了,不过其中有些细节方面博主很想借此机会,好好总结一下。 今天主要介绍以下几点: 1. 变量提升 2. 函数提升 3....
  • 在进行web前端开发的时候,我们经常会遇到变量提升的情况,那么JS在解析变量的时候是如何做到提升的呢?今天小千就来带大家了解一下。 首先在JS中涉及两种作用域的问题,那么什么是作用域呢? 作用域是代码中所使用...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 99,998
精华内容 39,999
关键字:

js变量提升