1. // 定义一个User构造函数
  2. function User(properties){
  3. //遍历对象属性,确保它作用域正确
  4. for(var i in properties){
  5. (function(which){
  6. var p = i;
  7. //为属性创建获取器
  8. which["get"+i] = function(){
  9. return properties[p];
  10. };
  11. //为属性创建设置器
  12. which["set"+i] = function(val){
  13. properties[p] = val;
  14. //return properties[p];
  15. };
  16. })(this);
  17. }
  18. }
  19.  
  20. // 创建一个User实例
  21. var user = new User({
  22. name:"Bob",
  23. age:44,
  24. islive:true,
  25. money:50000,
  26. earn:5000,
  27. nation:"china",
  28. job:"web Dev"
  29. });
  30.  
  31. user.getname(); // 返回 "Bob"
  32. user.getage(); // 返回 "44"
  33.  
  34. user.getage.call(window); // 依然返回44
  35. user.getage.call({age: 23}); // 还是返回44

上面的这段代码(我们叫它代码段A吧)里, user.getage.call(window)user.getage.call({age: 23}) 返回的结果,虽然在意料之中,但是我却并不非常清楚的知道为什么是这样。

我只是大概的知道,之所以是这个结果,肯定跟User构造函数里的闭包有关系。

我认为User构造函数里有两个闭包,所以我猜想调用user.getage的时候,就生成了2个闭包作用域。

但这只是我的猜想,事实是不是这样的呢?我想到了一个办法来验证:使用console.dir()

  1. var getage = user.getage;
  2.  
  3. console.dir(getage);

输出如下:

从输出的对象结构,可以看到这个方法它的[[Scopes]]确实有两个Closure,而且每个Closure里面有些什么东西也显示出来了。

我猜想在执行getage方法时,会先执行第一个闭包作用域,也就是Closure 0,这个闭包是由代码段A里的以下代码生成的:

  1. which["get"+i] = function(){
  2. return properties[p];
  3. };

我觉得这里应该搞清楚闭包、闭包作用域、闭包包含的作用域 三个概念,否则理解起来会很蒙,搞不清楚。

闭包:就是以上代码所定义的函数which[“get”+i]。

闭包作用域:就是由以上代码生成的执行上下文空间,它就是对象结构图中的那个[[Scopes]]。

闭包包含的作用域:可以看到[[Scopes]]里面还包含了getage闭包引用的另外两个闭包的作用域里的变量:立即执行函数的作用域里的变量p 和 User函数作用域里的变量i变量properties

从对象结构里可以看到,闭包 Closure 0 里面存在一个变量p,因此执行闭包时,会去闭包作用域里搜索p,但搜索不到,因为p是在立即执行函数的作用域里定义的,所以会立即进入搜索Closure 0作用域的流程。

搜索Closure 0时,找到了p,并且发现p = i,此时p的定义找到了,但p等于i,所以进入搜索变量i的定义的流程。

因为变量i没有在立即执行函数里定义,所以Closure(User)被保留了下来,在立即执行函数的作用域里找不到变量i,就进入Closure(User)作用域寻找,找到了i,同时应为是立即执行函数,所以i的值一搜索到,就理解返回给p,并存入Closure 0作用域中,而Closure(User)中的i的值由于程序继续执行而变化,最后只会存入最后设置给i的值。

properties的值也是一样,在闭包作用域里找不到,就会去立即执行函数的作用域里找,找不到再去Closure(User)里找,找到了立即返回。

所以上面那段生成闭包 Closure 0 的代码执行后,返回的结果就是 properties[i],此时闭包作用域使用完毕,不再需要,可以回收,进入解析Closure(User)作用域的步骤

然后properties[i] 被解析为 properties[“age”],然后被返回。

javascript 闭包的理解(二)的更多相关文章

  1. javascript闭包的理解

    闭包是Javascript的一个难点,但也是一个很重要的知识点. 1.首先我们要知道变量作用域链 变量的作用域分两种:全局变量和局部变量.没有定义到任何函数中的变量为全局变量,在函数中定义的变量为局部 ...

  2. 我对 javascript 闭包的理解

    学js的学到闭包,但是理解不深. 后来看了一下这篇文章: 地址:http://leepiao.blog.163.com/blog/static/4850313020112835355917/ 内容如下 ...

  3. 对JavaScript闭包的理解

    闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 在开始了解闭包前我们必须要先理解JavaScript的变量作用域. 一.变量的作用域无非就是两 ...

  4. javascript 闭包的理解(一)

    过很多谈如何理解闭包的方法,但大多数文章,都是照抄或者解释<Javascript高级程序设计(第三版)>对于闭包的讲解,甚至例程都不约而同的引用高程三181页‘闭包与变量’一节的那个“返回 ...

  5. 关于Javascript 闭包的理解

    一.什么是闭包? 官方”的解释是:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.相信很少有人能直接看懂这句话,因为他描述的太学术.其实这句话 ...

  6. javascript闭包的理解和实例

    所谓闭包,值得是词法表示包括不必要计算的变量的函数,也就是说,该函数可以使用函数外定义的变量. 顺便提示一下: 词法作用域:变量的作用域是在定义时决定而不是执行时决定,也就是说词法作用域取决于源码,通 ...

  7. Javascript闭包简单理解

    提到闭包,想必大家都早有耳闻,下面说下我的简单理解.平时写代码.第三方框架和组件都或多或少用到了闭包.所以,了解闭包是非常必要的.呵呵... 一.什么是闭包简而言之,就是能够读取其他函数内部变量的函数 ...

  8. Javascript 回调函数理解---二娃子买肾机6

    在Javascript中什么是回调函数,我认为简单来说就是把一个函数B作为参数传递给另一个函数A,在A函数中的一定时机调用函数B. 这里可以看出回调函数形成了一个闭包,它可以访问函数A中的活动对象. ...

  9. 关于Javascript闭包的理解

    以下内容属个人理解,如有看不明白或漏洞之处,纯属水平不佳,还望见谅. 关于闭包,高程里的定义是:指有权访问另一个函数作用域中的变量的函数.创建闭包最常见的方法就是在一个函数的内部再创建一个函数. 这里 ...

随机推荐

  1. C/S和B/S交互 2016-03-19 11:27 1275人阅读 评论(30) 收藏

    最近一直在做C/S的项目,每天都超忙,抽个时间写篇博客,之前一直做C/S项目就是各种窗体,各种控件,拖来拖去,然后点进去写方法,做BS的时候呢,因为一直使用的是mvc,所以就是经常手写代码,或者拖引用 ...

  2. 在WPF中绘制多维数据集

    原文 https://stuff.seans.com/2008/08/13/drawing-a-cube-in-wpf/ 是时候使用WPF绘制一个简单的3D对象了.作为WPF中3D图形的快速介绍,让我 ...

  3. 2018-8-10-win10-uwp-使用动画修改-Grid-column-的宽度

    title author date CreateTime categories win10 uwp 使用动画修改 Grid column 的宽度 lindexi 2018-08-10 19:17:19 ...

  4. SDUT-2130_数据结构实验之数组一:矩阵转置

    数据结构实验之数组一:矩阵转置 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 数组--矩阵的转置 给定一个m*n的矩阵 ...

  5. 2019-2-24-VisualStudio-过滤输出窗口文本

    title author date CreateTime categories VisualStudio 过滤输出窗口文本 lindexi 2019-2-24 11:10:7 +0800 2019-0 ...

  6. HDU - 6534 Chika and Friendly Pairs

    这个题其实也是很简单的莫队,题目要求是给一个序列,询问l-r区间内部,找到有多少对答案满足 i < j 并且 | a[ i ] -a[ j ] | <=k 也就是有多少对,满足差值小于k的 ...

  7. 异常解决:non-compatible bean definition of same name and class【com.xxx.xxx.XXX】

    昨天同事遇到这样一个问题,意思是spring找到 有相同的实现类名在不同的package目录下. 跟踪他的项目代码并未发现问题.   重新给他的maven项目进行maven install一下. 查看 ...

  8. H3C路由器SSH服务配置命令

  9. DTCC 2019 | 深度解码阿里数据库实现 数据库内核——基于HLC的分布式事务实现深度剖析

    摘要:分布式事务是分布式数据库最难攻克的技术之一,分布式事务为分布式数据库提供一致性数据访问的支持,保证全局读写原子性和隔离性,提供一体化分布式数据库的用户体验.本文主要分享分布式数据库中的时钟解决方 ...

  10. pytorch adam 源码 关于优化函数的调整 optimizer 调参 重点

    关于优化函数的调整拆下包:https://ptorch.com/docs/1/optim class torch.optim.Optimizer(params, defaults)所有优化的基类. 参 ...