在chrome的开发者工具中,通过断点调试,我们能够非常方便的一步一步的观察JavaScript的执行过程,直观感知函数调用栈,作用域链,变量对象,闭包,this等关键信息的变化。因此,断点调试对于快速定位代码错误,快速了解代码的执行过程有着非常重要的作用,这也是我们前端开发者必不可少的一个高级技能。

函数在被调用执行时,会创建一个当前函数的执行上下文。在该执行上下文的创建阶段,变量对象、作用域链、闭包、this指向会分别被确定。JavaScript程序中一般有多个函数,JavaScript引擎使用函数调用栈来管理这些函数的调用顺序,函数调用栈的调用顺序与栈数据结构一致。

代码段1

var fn;
function funcOut(){
    var a = 2;
    function funcIn(){
        console.log(a);
    }
    fn = funcIn;
}
function funcTest(){
    fn();
}
funcOut();
funcTest();

在funcOut()处设置断点,刷新页面;

点击step into,注意观察下方call stack与scope的变化,以及函数执行位置的变化。

我们可以看到,在funcOut内部声明的funcIn函数在调用时访问了它的变量a,因此funcOut成为了闭包。

代码段2

var fn;
var n = 20;
function funcOut(){
    var a = 2;
    function funcIn(a){
        console.log(a);
    }
    fn = funcIn;
}
function funcTest(){
    fn(n);
}
funcOut();
funcTest();

闭包没了,作用域链中没有包含funcOut了。

代码段3

function funcOut() {
    var a = 2;
    return function funcIn() {
        var b = 20;

        return function fn() {
            console.log(a);
        }
    }
}
var funcIn = funcOut();
var fn = funcIn();
fn();

fn只访问了funcOut中的a变量,因此它的闭包只有funcOut。

代码段4

function funcOut() {
    var a = 2;
    return function funcIn() {
        var b = 20;

        return function fn() {
            console.log(a,b);
        }
    }
}
var funcIn = funcOut();
var fn = funcIn();
fn();//2 20

这个时候,闭包变成了两个。分别是funcIn,funcOut。

代码段5

//闭包在模块中的应用
(function() {
    var a = 10;
    var b = 20;
    var myObj = {
        c: 20,
        sum1: function(x) {
            return a + x;
        },
        sum2: function() {
            return a + b + this.c;
        },
        sum3: function(k, j) {
            return k + j;
        }
    }
    window.myObj = myObj;
})();

myObj.sum1(100);
myObj.sum2();
myObj.sum3();

var funcTest = myObj.sum3;
funcTest();

sum1执行时,闭包为外层的自执行函数,this指向myObj。

sum2执行时,闭包为外层的自执行函数,this指向myObj。

sum3执行时,闭包为外层的自执行函数,this指向myObj。

funcTest执行时,闭包为外层的自执行函数,this指向Window。

这里的this指向显示为Object或者Window,大写开头,他们表示的是实例的构造函数,实际上this是指向的具体实例。

代码段6

var a = 10;
var obj = {
    a: 20
}
function fn() {
    console.log(this.a);
}
fn.call(obj); 

代码段7

function funcOut() {
  var a = 10;
  function funcIn1() {
      return a;
  }
  function funcIn2() {
      return 10;
  }
  funcIn2();
}

funcOut();

这个例子,和其他例子不太一样。虽然funcIn2并没有访问到funcOut的变量,但是funcOut执行时仍然变成了闭包。而当我将funcIn1的声明去掉时,闭包便不会出现了。我暂时也不知道应该如何解释这种情况。只能大概知道与funcIn1有关,可能浏览器在实现时就认为只要存在访问上层作用域的可能性,就会被当成一个闭包吧。

在chrome开发者工具中观察函数调用栈、作用域链、闭包的更多相关文章

  1. 在chrome开发者工具中观察函数调用栈、作用域链与闭包

    在chrome开发者工具中观察函数调用栈.作用域链与闭包 在chrome的开发者工具中,通过断点调试,我们能够非常方便的一步一步的观察JavaScript的执行过程,直观感知函数调用栈,作用域链,变量 ...

  2. 前端基础进阶(六):在chrome开发者工具中观察函数调用栈、作用域链与闭包

    在前端开发中,有一个非常重要的技能,叫做断点调试. 在chrome的开发者工具中,通过断点调试,我们能够非常方便的一步一步的观察JavaScript的执行过程,直观感知函数调用栈,作用域链,变量对象, ...

  3. 【译】在 Chrome 开发者工具中调试 node.js

    原文链接 : Debugging Node.js in Chrome DevTools 原文作者 : MATT DESLAURIERS 译文出自 : 掘金翻译计划 译文链接 : https://git ...

  4. 使用chrome开发者工具中的network面板测量网站网络性能

    前面的话 Chrome 开发者工具是一套内置于Google Chrome中的Web开发和调试工具,可用来对网站进行迭代.调试和分析.使用 Network 面板测量网站网络性能.本文将详细介绍chrom ...

  5. 在 Chrome 开发者工具中调试 node.js

    命令行工具 devtool ,它可以在 Chrome 的开发者工具中运行 Node.js 程序. 下面的记录显示了在一个 HTTP 服务器中设置断点的情况. 该工具基于 Electron 将 Node ...

  6. Chrome 开发者工具中的命令菜单

    单 大家对命令菜单(Command Menu)应该都不陌生.目前主流的编辑器中都内置了对该功能的支持.在 Sublime Text 和 Visual Studio Code 中你都可以通过快捷键 Ct ...

  7. Chrome开发者工具中Elements(元素)断点的用途

    SAP Engagement Center UI的这个按钮会每秒钟刷新一次,显示页面已经打开了多长时间. 需求:需要找到哪行JavaScript代码不断刷新的按钮文字. 按照经验判断,这个文字肯定是一 ...

  8. 使用chrome开发者工具中的performance面板解决性能瓶颈

    前面的话 使用Chrome DevTools的performance面板可以记录和分析页面在运行时的所有活动.本文将详细介绍如何使用performance面板解决性能瓶颈 准备 [匿名模式] 匿名模式 ...

  9. 使用 Chrome 开发者工具进行 JavaScript 问题定位与调试

    转自:https://www.ibm.com/developerworks/cn/web/1410_wangcy_chromejs/ 引言 Google Chrome 是由 Goole 公司开发的一款 ...

随机推荐

  1. HDU 4500 小Q系列故事——屌丝的逆袭

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4500 解题报告:简单题,数据范围不大,直接暴力每个点,然后再比较出得分最大的点的位置和分数. #inc ...

  2. 2019年湖南多校第一场||2018-2019 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2018)

    第一场多校就打的这么惨,只能说自己太菜了,还需继续努力啊- 题目链接: GYM链接:https://codeforces.com/gym/101933 CSU链接:http://acm.csu.edu ...

  3. Node程序debug小记

    有时候,所见并不是所得,有些包,你需要去翻他的源码才知道为什么会这样. 背景 今天调试一个程序,用到了一个很久之前的NPM包,名为formstream,用来将form表单数据转换为流的形式进行接口调用 ...

  4. go 匿名函数和闭包

    匿名函数 1. 函数也是一种类型,因此可以定义作为一个函数类型的变量 package main import "fmt" // 函数作为参数 func add(a, b int) ...

  5. fc26 url

    aarch64 http://linux.yz.yamagata-u.ac.jp/pub/linux/fedora-projects/fedora-secondary/releases/26/Ever ...

  6. Mac上删除不了的文件,Windows上也粉碎不了怎么办?

    推荐一个Mac上的软件:Tuxera Disk Manager 用法很简单:选择删除文件原来所在的文件进行维护就可以了. 维护之后,在废纸篓中清除,成功.

  7. Python函数:对变量赋值,变量即局部

    b = 6 def f2(a): print(a) print(b) b = 9 UnboundLocalError: local variable 'b' referenced before ass ...

  8. .NET 4.5 Task异步编程学习资料

    参考资料: 1. http://www.cnblogs.com/heyuquan/archive/2013/04/18/3028044.html

  9. Python_oldboy_自动化运维之路(四)

    本节内容 集合 字符编码与转码 函数语法及基本特性 函数参数与局部变量 返回值和嵌套函数 递归 匿名函数 高阶函数 1.集合 集合是一个无序的,不重复的数据组合,它的主要作用如下: 去重,把一个列表变 ...

  10. java基础28 单例集合Collection下的List和Set集合

    单例集合体系: ---------| collection  单例集合的根接口--------------| List  如果实现了list接口的集合类,具备的特点:有序,可重复       注:集合 ...