在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 2571 命运 (入门dp)

    题目链接 题意:二维矩阵,左上角为起点,右下角为终点,如果当前格子是(x,y),下一步可以是(x+1,y),(x,y+1)或者(x,y*k) ,其中k>1.问最大路径和. 题解:入门dp,注意负 ...

  2. python初步学习-练习题

    1.实现1-100的所有的和 #!/usr/bin/env python #encoding:utf8 '''实现1-100的所有的和 1. 使用列表解析获取0-100的列表 2. 使用reduce内 ...

  3. 字符串hash&&对字符串hash的理解

     对字符串hash的一些总结: 1,首先,我们在转化的时候,取底的时候一般是取131这些数,因为要避免不同的字符串对应相同的hash值这种情况的出现.如果卡精度的时候,我们可以采取双模数的方式尽量减少 ...

  4. 使用python开发一个能够计算带括号的复杂表达式的计算器(只支持加减乘除)

    使用到了模块re,正则,字典等 # 实现简单的加减乘除括号等运算 # Calculator def calculator(expression): print(expression) import r ...

  5. 公司xenserver搭建的使用

    [root@xenserver ~]# ls -l /dev/disk/by-path/total 0lrwxrwxrwx 1 root root  9 Jan 19 16:33 pci-0000:0 ...

  6. 如何同步删除svn管理的package包目录

    转:https://blog.csdn.net/shiwodecuo/article/details/51754598 eclipse在实际的开发中,当我们的项目由svn进行管理时,若想删除选中的整个 ...

  7. 在Mac上搭建ReactNative开发环境

    1.安装Homebrew,   Mac系统的包管理器,用于安装NodeJS和一些其他必需的工具软件. /usr/bin/ruby -e "$(curl -fsSL https://raw.g ...

  8. 【前端开发】前端引入公共部分footer header的几种方法,及iframe自适应高度js

    一.引入页面几种方法   1.IFrame引入,看看下面的代码    <iframe   frameborder=0   border=0   width=300   height=300    ...

  9. 本地为Windows,使用Xshell登录Linux云主机

    以某东的云主机为实例 1. 下载并安装远程登录软件 下载Xshell软件 下载后双击xshell5_5.0.1332.exe进行安装 2. 安装完成,打开Xshell,并点击新建,根据要求输入相应参数 ...

  10. SQLSERVER中的系统存储过程的使用的总结

    -----------------------------系统存储过程-------------------------------- --列出SQL Server实例中的数据库sp_database ...