javascript 执行环境,作用域链和闭包
首先看下这条语句:
(function($) {…})(jQuery);
1.原理:
function(arg){…}
这就定义了一个匿名函数,参数为arg
而调用函数时,是在函数后面写上括号和实参的,由于操作符的优先级,函数本身也需要用括号,即:
(function(arg){…})(param)
这就相当于定义了一个参数为arg的匿名函数,并且将param作为参数来调用这个匿名函数
而(function($){…})(jQuery)则是一样的,之所以只在形参使用$,是为了不与其他库冲突,所以实参用jQuery
相当于
funtion output(s){…};
output(jQuery);
或者
var fn=function(s){…};fn(jQuery);
2.作用:
这种写法的最大好处是形成闭包。在(function($) {…})(jQuery)在内部定义的函数和变量只能在此范围内有效。
形成私有函数、私有变量的概念。
几个概念:
1、执行环境(execution context):
每个函数都有自己的执行环境,当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。而在函数执行后,栈将其环境弹出,把控制权返回给之前的执行环境。
2、作用域链(scope chain):
函数的内部环境可以通过作用域链访问到所有的外部环境,但是外部环境却不可以访问外部环境,这就是作用域
ES5中只有全局作用域和函数作用域,没有块级作用域。
(但在ES6中多了一个let,他可以保证外层块不受内层块的影响。即内层块形成了一个块级作用域,这是let的一个特点。
它不简单,因为在许多的函数嵌套的情景下,只有对它理解深刻,才能更好的去分析。)
3、闭包 :指有权访问另一个函数作用域中的变量的函数
创建闭包的常见方式,就是在一个函数内部创建另一个函数(通常是匿名函数)。
在一个函数a内部定义的另一个函数b,当b在a之外被执行时,就会形成闭包。同时b函数仍然可以访问到a函数中的局部变量与函数。
弊端:闭包会携带包含他的函数的作用域,会比其他函数占用更多的内存。所以请慎用闭包
function fn(){
var array=[];
for(var i=0;i<10;i++){
array[i]=function(){
return i;
}
}
return array;
}
fn();//[ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ]
我们的本意是得到这个数组中每个函数都能返回自己的索引值,可是得到的是每个函数却都返回了10.
闭包保存的是定义它的那个函数内部的局部变量丶参数和其他内部函数,也就是说保存的是这个函数执行上下文中的整个VO,而不是一个变量。上面代码中的函数作用域链中都保存着fn的活动对象,他们引用的都是一个i,当fn返回时,i的值是10,所以每个函数都引用保存i那个变量的同一个变量。我们如果想得到原先想得到的那个结果,可以加上另一个匿名函数改变他的父作用域(其实应该是创建它的作用域),将它包裹起来。
function fn(){
var array=[];
for(var i=0;i<10;i++){
array[i]=function(num){
return function(){
return num;
};
}(i);
}
return array;
}
这个匿名函数有一个参数num,同时是返回值。在调用每个匿名函数时,传入了变量i。由于参数是按值传递的,所以i就会复制给num,而这个匿名函数的内部又创建了一个访问num的闭包,返回后能够访问到该匿名函数中的VO(包括参数),于是每个函数返回的都是num的一个副本,所以可以得到不同的值。
其实,说了这么多,我们只要熟悉闭包的两个应用场景,就能比较好的理解闭包的意义。
一.作为函数的返回值.。作为函数返回值被执行后仍然可以访问定义它的那个函数环境的VO。
function f(){
var a=1;
return function(){
console.log(a);
}
}
var g=f();
g();//1;
二.作为一个函数的参数。作为函数返回值被当做另一个函数的参数传入时,仍然是访问定义它的那个函数环境的VO
function f(){
var a=1;
return function(){
console.log(a);
}
}
var g=f();
g();//1;
function F(fn){
var a=2;
fn();
}
F(g);//
上面两个小例子也正好说明了闭包可以访问定义它的那个函数作用域下的内部变量和内部函数。其实是整个VO,所以还包含参数。
关于this对象
我们知道,this对象是在运行时基于函数的执行环境绑定的,全局函数中,this=window;
当某个函数被作为某个对象的方法调用时,this=对象
匿名函数的执行环境具有全局性,因此其this对象通常指向window
所以在闭包中使用this对象或arguments对象,必须将该对象的引用保存到闭包能够访问到的另一个变量中。
javascript 执行环境,作用域链和闭包的更多相关文章
- javascript深入浅出图解作用域链和闭包
一.概要 对于闭包的定义(红宝书P178):闭包就是指有权访问另外一个函数的作用域中的变量的函数. 关键点: 1.闭包是一个函数 2.能够访问另外一个函数作用域中的变量 文章首发地址于sau交流学习社 ...
- 《浏览器工作原理与实践》<10>作用域链和闭包 :代码中出现相同的变量,JavaScript引擎是如何选择的?
在上一篇文章中我们讲到了什么是作用域,以及 ES6 是如何通过变量环境和词法环境来同时支持变量提升和块级作用域,在最后我们也提到了如何通过词法环境和变量环境来查找变量,这其中就涉及到作用域链的概念. ...
- javascript 执行环境,变量对象,作用域链
前言 这几天在看<javascript高级程序设计>,看到执行环境和作用域链的时候,就有些模糊了.书中还是讲的不够具体. 通过上网查资料,特来总结,以备回顾和修正. 要讲的依次为: EC( ...
- JavaScript 执行环境以及作用域链
执行环境(execution context,为简单起见,有时也称为"环境")是 JavaScript 中最为重要的一个概念.执行环境定义了变量或函数有权访问的其他数据,决定了它们 ...
- 个人理解的javascript作用域链与闭包
闭包引入的前提个人理解是为从外部读取局部变量,正常情况下,这是办不到的.简单的闭包举例如下: function f1(){ n=100; function f2(){ alert(n); } retu ...
- JavaScript 执行环境、作用域、内存管理及垃圾回收机制
前言 JavaScript具有自动垃圾收集机制,也就是说,执行环境会负责管理代码执行过程中使用的内存. [原理]找出那些不再继续使用的变量,然后释放其占用的内存.为此,垃圾收集器会按照固定的时间间隔( ...
- 图解Javascript——作用域、作用域链、闭包
什么是作用域? 作用域是一种规则,在代码编译阶段就确定了,规定了变量与函数的可被访问的范围.全局变量拥有全局作用域,局部变量则拥有局部作用域. js是一种没有块级作用域的语言(包括if.for等语句的 ...
- 【进阶2-2期】JavaScript深入之从作用域链理解闭包(转)
这是我在公众号(高级前端进阶)看到的文章,现在做笔记 https://github.com/yygmind/blog/issues/18 红宝书(p178)上对于闭包的定义:闭包是指有权访问另外一 ...
- 1--面试总结-js深入理解,对象,原型链,构造函数,执行上下文堆栈,执行上下文,变量对象,活动对象,作用域链,闭包,This
参考一手资料:http://dmitrysoshnikov.com/ecmascript/javascript-the-core/中文翻译版本:https://zhuanlan.zhihu.com/p ...
- 理解JavaScript中的作用域链
理解了作用域链,闭包就不难理解了,所以本文主要谈一谈我对作用域链的理解. 关于JavaScript中变量的作用域,全局变量在程序中始终都有定义.局部变量在声明它的函数体内以及其内部所嵌套的函数内始 ...
随机推荐
- Unity3D深入浅出 -组件与节点之间的调用关系
一.transform组件用途 1.维护场景树 2.对3D物体的平移,缩放,旋转 二.场景树定义 在Hierarchy视图中显示的: 一个game_scene场景,下面有Main Camera节点,D ...
- jvm载入过程
类载入过程 类从被载入到虚拟机内存中開始,到卸载出内存为止,它的整个生命周期包含:载入.验证.准备.解析.初始化.使用和卸载七个阶段.它们開始的顺序例如以下图所看到的: 当中类载入的过程包含了载入.验 ...
- IFrame实现的无刷新(仿ajax效果)...
前台代码: <iframe style="display:none;" name="gg"></iframe> <form act ...
- php对gzip的使用(实例)
代码如下: if (!function_exists('gzdecode')) { function gzdecode ($data) { $flags = ord(substr($data, 3, ...
- ReSharper插件功能介绍
ReSharper是一款功能非常强悍的Visual Studio的辅助插件,这款插件可用于C#,VB.net,XML,Asp.net,XAML,和构建脚本.ReSharper 9.1版本大改进对 Ja ...
- 怎么用MathType编辑带圈字母
在用word公式编辑器MathType编辑公式时,里面涉及到很多的数学物理符号等等,这些符号或者是公式其实都可以利用MathType中的模板进行组合.在这些数学公式中,有时会有一些比较特殊的符号,它们 ...
- matlab彩色图像插值
软件是MATLAB R2014b 使用的是matlab中已有的函数imresize(); 彩色图像分别对R.G.B三个通道进行插值,之后融合.[imresize函数不用,可以直接插值] clear;c ...
- HTML <a> 标签的状态和 target 属性
<a>的四种状态 A:link 连接平常状态 A:hover 鼠标放上去的时候 A:active 鼠标按下的时候 A:visited 连接被访问过后的状态 target属性 _bla ...
- Linux lspci 命令
PCI(Peripheral Component Interconnect,外设部件互连标准),即定义连接外部设备的一个标准: 主板上有很多 PCI 接口,用来连接显卡.网卡.声卡等外部设备,而 ls ...
- Qt监控excel
配置文件setup.ini内容 [General] ExcelFilePath=D:/项目资料/GSC-西门子开关/GSCOPC.xlsx GameIp=192.168.1.152 GamePort= ...