javascript 闭包的理解(二)
// 定义一个User构造函数
function User(properties){
//遍历对象属性,确保它作用域正确
for(var i in properties){
(function(which){
var p = i;
//为属性创建获取器
which["get"+i] = function(){
return properties[p];
};
//为属性创建设置器
which["set"+i] = function(val){
properties[p] = val;
//return properties[p];
};
})(this);
}
} // 创建一个User实例
var user = new User({
name:"Bob",
age:44,
islive:true,
money:50000,
earn:5000,
nation:"china",
job:"web Dev"
}); user.getname(); // 返回 "Bob"
user.getage(); // 返回 "44" user.getage.call(window); // 依然返回44
user.getage.call({age: 23}); // 还是返回44
上面的这段代码(我们叫它代码段A吧)里, user.getage.call(window) 和 user.getage.call({age: 23}) 返回的结果,虽然在意料之中,但是我却并不非常清楚的知道为什么是这样。
我只是大概的知道,之所以是这个结果,肯定跟User构造函数里的闭包有关系。
我认为User构造函数里有两个闭包,所以我猜想调用user.getage的时候,就生成了2个闭包作用域。
但这只是我的猜想,事实是不是这样的呢?我想到了一个办法来验证:使用console.dir()
var getage = user.getage; console.dir(getage);
输出如下:
从输出的对象结构,可以看到这个方法它的[[Scopes]]确实有两个Closure,而且每个Closure里面有些什么东西也显示出来了。
我猜想在执行getage方法时,会先执行第一个闭包作用域,也就是Closure 0,这个闭包是由代码段A里的以下代码生成的:
which["get"+i] = function(){
return properties[p];
};
我觉得这里应该搞清楚闭包、闭包作用域、闭包包含的作用域 三个概念,否则理解起来会很蒙,搞不清楚。
闭包:就是以上代码所定义的函数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 闭包的理解(二)的更多相关文章
- javascript闭包的理解
闭包是Javascript的一个难点,但也是一个很重要的知识点. 1.首先我们要知道变量作用域链 变量的作用域分两种:全局变量和局部变量.没有定义到任何函数中的变量为全局变量,在函数中定义的变量为局部 ...
- 我对 javascript 闭包的理解
学js的学到闭包,但是理解不深. 后来看了一下这篇文章: 地址:http://leepiao.blog.163.com/blog/static/4850313020112835355917/ 内容如下 ...
- 对JavaScript闭包的理解
闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 在开始了解闭包前我们必须要先理解JavaScript的变量作用域. 一.变量的作用域无非就是两 ...
- javascript 闭包的理解(一)
过很多谈如何理解闭包的方法,但大多数文章,都是照抄或者解释<Javascript高级程序设计(第三版)>对于闭包的讲解,甚至例程都不约而同的引用高程三181页‘闭包与变量’一节的那个“返回 ...
- 关于Javascript 闭包的理解
一.什么是闭包? 官方”的解释是:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.相信很少有人能直接看懂这句话,因为他描述的太学术.其实这句话 ...
- javascript闭包的理解和实例
所谓闭包,值得是词法表示包括不必要计算的变量的函数,也就是说,该函数可以使用函数外定义的变量. 顺便提示一下: 词法作用域:变量的作用域是在定义时决定而不是执行时决定,也就是说词法作用域取决于源码,通 ...
- Javascript闭包简单理解
提到闭包,想必大家都早有耳闻,下面说下我的简单理解.平时写代码.第三方框架和组件都或多或少用到了闭包.所以,了解闭包是非常必要的.呵呵... 一.什么是闭包简而言之,就是能够读取其他函数内部变量的函数 ...
- Javascript 回调函数理解---二娃子买肾机6
在Javascript中什么是回调函数,我认为简单来说就是把一个函数B作为参数传递给另一个函数A,在A函数中的一定时机调用函数B. 这里可以看出回调函数形成了一个闭包,它可以访问函数A中的活动对象. ...
- 关于Javascript闭包的理解
以下内容属个人理解,如有看不明白或漏洞之处,纯属水平不佳,还望见谅. 关于闭包,高程里的定义是:指有权访问另一个函数作用域中的变量的函数.创建闭包最常见的方法就是在一个函数的内部再创建一个函数. 这里 ...
随机推荐
- Java练习 SDUT-2670_3-1 Point类的构造函数
3-1 Point类的构造函数 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 通过本题目的练习可以掌握类的构造函数的定 ...
- UVA_458:The Decoder
Language:C++ 4.8.3 PS:ASCII值减去七 #include<stdio.h> #include<string.h> int main(void) { c ...
- QT自定义窗口
qt 中允许自定义窗口控件,使之满足特殊要求, (1)可以修改其显示,自行绘制 (2)可以动态显示 (3)可以添加事件,支持鼠标和键盘操作 自定义控件可以直接在QtDesigner里使用,可以直接加到 ...
- qt开发ROS gui 遇到:global.h:1087:4: error: #error "You must build your code with position independent code if Qt was built with -reduce-relocations. "......
具体错误如下: 一共出现38个错误 这个错误是在导入cmakelists.txt时产生的,其实不是工程本身的问题,是因为我卸载ros,再重新安装ros的过程中把qtcreator的部分包给删除了,导致 ...
- @loj - 2092@ 「ZJOI2016」大森林
目录 @description@ @solution@ @accepted code@ @details@ @description@ 小 Y 家里有一个大森林,里面有 n 棵树,编号从 1 到 n. ...
- oracle函数 NLS_UPPER(x[,y])
[功能]返回字符串并将字符串的转换为大写; [参数]x字符型表达式 [参数]Nls_param可选,指定排序的方式(nls_sort=) . SCHINESE_RADICAL_M(部首.笔画) SCH ...
- 字母间距letter-spacing
效果图: 字母间距CSS: h1 {letter-spacing:2px} h2 {letter-spacing:-3px}
- day5_python之subprocess模块
subprocess作用:用来执行系统命令它会开启一个子进程,通过子进程去执行一些命令 读取正确的命令执行结果,如果没有指定把结果输出到哪里,默认打印到屏幕上 #subprocess.Popen(r' ...
- 对装饰器@wraps的解释(一看就懂)-- 并对装饰器详解
1. 先看一段代码 def is_login(func): def foo(*args,**kwargs): return func(*args,**kwargs) return foo def te ...
- em&rem
PX特点 1. IE无法调整那些使用px作为单位的字体大小: 2. 国外的大部分网站能够调整的原因在于其使用了em或rem作为字体单位: 3. Firefox能够调整px和em,rem px像素(Pi ...