闰土说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)

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

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏屈定‘s Blog

设计模式--组合模式的思考

组合模式是一种抽象树形结构的模式,其在业务开发中也是一种很有用的设计模式,下面开始分析.

4213
来自专栏黑泽君的专栏

Eclipse保存文件时出现字符编码错误

eclipse 由于开源所以支持了比较杂的编码方式,而这些一个工程导入时添加了不少的外来程序,由于不是同一工程一次编码带来了其中含有 GBK 或 UTF8 或 ...

3201
来自专栏每周一脱topic

Effictive python学习总结连载(1)

python从读研开始就在用了,拿来做过web后台、安全分析、爬虫、测试框架等等,挺强大的。最近借放假和看书和整理的机会,系统的总结下。主要是2方面:一个是书或...

2152
来自专栏java学习

Java每日一练(2017/7/6)

最新通知 ●回复"每日一练"获取以前的题目! ●【新】Ajax知识点视频更新了!(回复【学习视频】获取下载链接) ●答案公布时间:为每期发布题目的第二天 ★【新...

3459
来自专栏Web 开发

JavaScript Cookbook 2nd 之 Function

昨晚翻了一下,虽然都是一些旧知识,不过深入下去对照着其他资料一起看,还是能发现一些有意思的地方。

920
来自专栏Java爬坑系列

【JAVA零基础入门系列】Day11 Java中的类和对象

  今天要说的是Java中两个非常重要的概念——类和对象。   什么是类,什么又是对象呢?类是对特定集合的概括描述,比如,人,这个类,外在特征上,有名字,有年龄...

19910
来自专栏AndroidTv

谈谈你对 Java 平台的理解声明提问正文

1164
来自专栏醒者呆

基础大扫荡——背包,栈,队列,链表一口气全弄懂

提到数据结构,不得不说数据类型,有人将他们比作分子和原子的关系,我们都知道大自然最小的构成单位是原子,数据类型描述的是原子的内部,如质子、中子的情况,而数据结构...

42715
来自专栏JetpropelledSnake

Python入门之字符编码

一、字节编码的基础知识 一、计算机基础知识 #1 我们的程序都是运行在特定的操作系统内,例如window,linux,mac等等 #2 运行应用程序,需要要操作...

3428
来自专栏Crossin的编程教室

【Python 第23课】 if, elif, else

今天补充之前讲过的一个语句:if。为什么我跳要着讲,因为我的想法是先讲下最最基本的概念,让你能用起来,之后你熟悉了,再说些细节。 关于if,可以发送数字『7』回...

2856

扫码关注云+社区

领取腾讯云代金券