美文网首页饥人谷技术博客
JS作用域链和声明前置的理解

JS作用域链和声明前置的理解

作者: 老虎爱吃母鸡 | 来源:发表于2016-07-21 14:30 被阅读0次

例题:

    var a = 1;
    function fn() {
        var a 
        console.log('1.'+a);//undefined
        a = 5;
        console.log('2.'+a);//5
        function fn2() {
            console.log('3.'+a);//6
            a = 20;
        }
        a++;
        fn2();
        console.log('4.'+a);//20
    }
    fn();
    console.log('5.'+a);//1

例题中的作用域链:

        //全局作用域下的变量对象
    window.scope={
        a://var a = 1的时候是1,a = 10的时候为10,
        fn:function () {
            ...
        }
    }
    //fn()作用域下的变量对象
    1.fn.scope={
        a://声明的时候是undefined,a = 5的时候是5,a++的时候是6,fn2()中a = 20赋值过后是20,
        fn2:function () {
            ...
        }
    }
    2.window.scope={
        a:1,
        fn:function () {
            ...
        }
    }
    //fn2()作用域下的变量对象
    1.fn2.scope={}
    2.fn.scope={
        a://声明的时候是undefined,a = 5的时候是5,a++的时候是6,fn2()中a = 20赋值过后是20
        fn2:function () {
            ...
        }
    }
    3.window.scope={
        a:1,
        fn:function () {
            ...
        }
    }

console.log('1.'+a):在JS中的语句var a = 1其实是两条语句var aa = 1的合并,其中语句var a由于声明前置会被提到作用域的开头,例如:

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

这个console.log(a)会输出undefined。


console.log('2.'+a):在fn()的作用域中,a已经被声明过,所以a = 5就直接将5赋值给a。


console.log('3.'+a):为什么会输出6呢,因为:

  1. 在进入fn2()的执行环境之前,有一个a++
  2. fn2()的作用域中没有声明a,在调用a这个变量的时候就会顺着作用域链往外层查找,在fn()的作用域中找到了已经被声明的a

console.log('4.'+a):不是说好的外层作用域不能访问内层吗,可是为什么fn2()中的a = 20会影响到fn()里的a呢?因为:

  • fn2()中的a = 20改变的本来就是fn()中声明过的a的值

console.log('5.'+a):在fn2()中a = 20没有var关键字,不是说在函数内没有使用var关键字直接给变量赋值会成为全局变量吗,这里的console.log输出不应该是20吗,为什么还是1呢?

  1. 首先我们看看为什么函数内没有加var关键字的变量会变成全局变量呢?
    例如:

     function fn() {
         b = 1;
     }
     fn();
    

    我们都知道,在全局作用域下的变量和函数都是window对象的属性和方法。其实在fn()被调用的时候,b = 1顺着作用域链想找到被声明的b赋值,但是无论fn()的作用域还是全局作用域都没声明b,所以解析器就做了window.b=1这样一个行为,就是给window对象加了一个b:1的名值对。

  2. 然后为什么fn2()的a = 20没有加到全局对象上呢?
    因为fn2()顺着作用域链查找的时候在fn()的作用域中找到了已经被声明过的a,所以20就直接赋值给了fn()中已经声明过的a。


相关文章

  • zj3 函数与作用域

    讲解函数声明、函数表达式、声明前置、作用域、作用域链相关概念 函数声明和函数表达式有什么区别 什么是变量的声明前置...

  • JS作用域链和声明前置的理解

    例题: 例题中的作用域链: console.log('1.'+a):在JS中的语句var a = 1其实是两条语句...

  • JavaScript 函数闭包(colsure)

    理解闭包,你首先必须理解JS的变量作用域,JavaScript作用域和作用域链。 ES6之前,变量的作用域分为全局...

  • 3小时速学JS原理

    内容:前端JS部分知识点原理速讲,内容包括且不限于 声明前置 引用类型 函数作用域链 闭包 跨域 面向对象 继承 ...

  • 总结篇(四) -- 进阶

    概述 本篇主要讲述声明前置、引用类型、函数作用域链、闭包、HTTP、Web安全和性能优化 声明前置 在进入一个执行...

  • JS博客

    JS构造函数及new运算符 JS原型对象和原型链 函数作用域和作用域链 干货分享:让你分分钟学会JS闭包 深入理解...

  • 前端基础(问答12)

    keywords:函数声明、函数表达式、声明前置、argument、重载、作用域链 函数声明和函数表达式有什么区别...

  • 2018-12-18

    JS高级 作用域&作用域链 作用域: 1.作用域的个数:n(函数声明的个数)+1(全局作用域)2.作用域不会存储变...

  • 函数&声明前置&作用域链

    1. 函数声明和函数表达式有什么区别 JavaScript函数是指一个特定代码块,可能包含多条语句,可以通过名字来...

  • 函数与作用域

    声明前置和作用域也是JS 部分面试常考点 1.函数声明和函数表达式有什么区别 函数声明:使用function关键字...

网友评论

    本文标题:JS作用域链和声明前置的理解

    本文链接:https://www.haomeiwen.com/subject/rfubjttx.html