专栏首页闰土大叔闰土说JS进阶之作用域链

闰土说JS进阶之作用域链

前言

在前端应聘中,相信会有不少面试官都会问你,说说你理解的js作用域,或者作用域链。显然,这是一道经典的js面试题,对于老司机而言可谓是小菜一碟,而对于前端新人,尤其是js基础不扎实的新人来说,则会说的模棱两可,含糊其辞。当然这样青涩的答案显然不会入面试官的法眼,甚至会让你白白丢掉一次面试机会。那么作用域链究竟好不好理解呢,接下来正文开始。

在说作用域前,我们先来说说什么是执行环境。新人容易把执行环境和作用域这两个概念搞混了,要知道函数的每次调用都有与之相关的作用域和执行环境。从根本上来说,作用域是基于函数的,而执行环境是基于对象的,举个栗子,全局执行环境是window对象。

执行环境,同行们也喜欢叫执行上下文。每个函数都有自己的执行环境,当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。而在函数执行之后,栈将其环境弹出,把控制权返回给之前的执行环境。

执行环境分为创建和执行两个阶段。在创建阶段,解析器首先会创建一个变量对象,也叫活动对象,俗称AO。它由定义在执行环境中的变量、函数声明和参数组成。在此期间,作用域链会被初始化,this的值也会被确定。而在执行阶段,代码便会被解释执行。

如果这时面试官问你作用域链的作用是什么?你是不是会瞬间懵逼?别急。且听闰土怎么说。那么这个问题的标准答案就是,作用域链的用途是用于解析标识符。(知道了吧,是不是该用笔记下来,或者划划重点啥的,闰老师说了,这是必考题,嘿嘿~)

标识符的解析是从作用域链的前端开始,沿着作用域链一级一级向后回溯,直至找到标识符为止。(如果找不到,则会报错)。

说了这么久,给大家举个栗子:

var food = '麻辣烫';



function changeFood(){
    var anotherFood = '过桥米线';


    function swapFood(){
        var tempFood = anotherFood;

        anotherFood = food;

        food = tempFood;

 

        //这里可以访问food、anotherFood、tempFood

    }



    //这里可以访问food、anotherFood
    swapFood();

}

//这里只能访问food
changeFood();

以上代码中,在swapFood()函数的局部环境中有个变量tempFood,这个变量只能在这个环境中访问到。无论全局环境还是changeFood()的局部环境都无权访问tempFood。而在swapFood()内部则可以访问其他两个环境中的所有变量,因为那两个环境是它的父执行环境。

总结一下,内部环境可以通过作用域链访问所有的外部环境,但外部环境不能访问内部环境中的任何变量和函数。

接下来,我们再来讲讲块级作用域。

在ES6没出来之前,javascript是没有块级作用域的。在这一点上,很多从后端转过来的前端人员都比较困惑,因为在C++或者java中,由花括号封闭的代码块都有自己的作用域,用ES自己的话来说,就是它们自己的执行环境。这也是我认为的js的一个缺陷。让我们一起来看看下面这个for循环的栗子:

for(var i=0;i<10;i++){
    console.log('i: ' + i);

}

console.log(i);  // 10

对于有块级作用域的语言来说,i变量会在for循环执行结束之后销毁,换句话说,它只会存在循环体内。而对于javascript来说,变量i即使在for循环执行结束以后,也依旧会存在于循环体外部的执行环境。所以最后console出来的i 是 10。扩展一下,如果用ES6的let来声明变量i,那么console出来的结果就是 i is not defined。因为ES6中的let声明的变量具有块级作用域的特性。

在javascript编码过程中,不声明而直接初始化一个变量是一个常见的错误做法,因为这样可能会导致意外。所以,想要了解大公司的javascript编码规范,首先要从细节开始,从初始化变量前先声明开始。

小结

每天进步一点点,每天消化掉一个小知识点,才能积少成多,最后量变导致质变。愿大家都能成为更好的前端,做更好的自己。

最后给大家放个彩蛋,看闰土哥在公园玩俯卧撑快闪,请为闰土少年打call!

视频内容

本文分享自微信公众号 - 闰土大叔(running_hacker)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-10-27

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 你离中级前端工程师还有多远?

    在昨天的文章 知乎高赞:拿4K的前端开发都会做些什么?中,我已经简单聊了聊初级前端的岗位职责、技能要求等,推文之后效果还不错,有很多在校生加我微信“聊人生”。那...

    闰土大叔
  • 前端找实习岗的7条建议

    最近,很多人给我留言,问我「前端初学者怎么才能找到一份实习工作」,或者是「前端学习到什么程度可以出去找工作」

    闰土大叔
  • 说真的,前端对Linux需要了解到什么程度?

    还记得土哥刚入行,进第一家公司实习的时候,使用的是Win7,对于Windows下的命令行体验真是无力吐槽,特别是对于Web前端来说,非常多的工具都运行在终端内,...

    闰土大叔
  • JavaScript之执行环境与作用域的区别与联系​

    如何一对花括号中的语句代码集都属于一个块,在这之中定义的所有变量在代码块外是不可见的,称为块级作用域。作用域控制着变量和参数的可见性与生命周期。

    达达前端
  • 几行代码理解Python变量访问的LEGB顺序

    Python变量访问时有个LEGB原则,也就是说,变量访问时搜索顺序为Local ==> Enclosing ==> Global ==> Builtin,听起...

    Python小屋屋主
  • JavaScript 作用域不完全指北

    对于几乎所有编程语言,最基本的功能之一就是能够存储变量的值,并且能在之后对这个值进行访问和修改。这样就会带来几个问题,这些变量存储在哪里?程序在需要的时候又是如...

    撸码那些事
  • 从 JavaScript 作用域说开去

    在电脑程序设计中,作用域(scope,或译作有效范围)是名字(name)与实体(entity)的绑定(binding)保持有效的那部分计算机程序。不同的编程语言...

    一缕殇流化隐半边冰霜
  • JS入门难点解析3-作用域

    (注1:如果有问题欢迎留言探讨,一起学习!转载请注明出处,喜欢可以点个赞哦!) (注2:更多内容请查看我的目录。)

    love丁酥酥
  • 稳扎稳打JavaScript(一)——作用域链内存模型

    几个概念 在开始之前,先了解几个概念。 1.1. 作用域 作用域是指当前正在执行的代码能够访问到变量的范围; 每个函数都有各自的作用域,存储函数所有的局部变量...

    大闲人柴毛毛
  • 理解javascript作用域和作用域链

    作用域就是变量和函数的可访问范围,控制着变量和函数的可见性与生命周期,在JavaScript中变量的作用域有全局作用域和局部作用域。

    令仔很忙

扫码关注云+社区

领取腾讯云代金券