重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
ES6 之前 JS 没有块级作用域。例如
成都创新互联提供网站设计、成都做网站、网页设计,品牌网站建设,1元广告等致力于企业网站建设与公司网站制作,十余年的网站开发和建站经验,助力企业信息化建设,成功案例突破数千家,是您实现网站建设的好选择.
从上面的例子可以体会到作用域的概念,作用域就是一个独立的 地盘 ,让变量不会外泄、暴露出去。上面的name就被暴露出去了,因此, JS 没有块级作用域,只有全局作用域和函数作用域 。
全局作用域就是最外层的作用域 ,如果我们写了很多行 JS 代码,变量定义都没有用函数包括,那么它们就全部都在全局作用域中。这样的坏处就是很容易撞车、冲突。
这就是为何 jQuery、Zepto 等库的源码,所有的代码都会放在 (function(){....})() 中。因为放在里面的所有变量,都 不会被外泄和暴露 ,不会污染到外面,不会对其他的库或者 JS 脚本造成影响。这是函数作用域的一个体现。
附:ES6 中开始加入了块级作用域,使用let定义变量即可,如下:
首先认识一下什么叫做 自由变量 。如下代码中,console.log(a)要得到a变量,但是在当前的作用域中没有定义a(可对比一下b)。当前作用域没有定义的变量,就称为 自由变量 。自由变量如何得到 —— 向 父级 作用域寻找。
如果父级也没呢? 再一层一层向上寻找,直到找到全局作用域还是没找到,就宣布放弃 。这种一层一层的关系,就是 作用域链 。
通过例子来理解闭包。
自由变量将从作用域链中去寻找,但是 依据的是函数定义时的作用域链,而不是函数执行时 ,以上这个例子就是闭包。闭包主要有 两个 应用场景:
1.函数 作为 返回值 ,上面的例子就是
2.函数 作为 参数 传递,看以下例子
通过文你将学到:
经常听到闭包这个词儿,或者匿名函数自执行,之类的。到底他们是一个东西吗?
我不想扣定义,直接上例子。
看图:
函数执行完以后会销毁(这里我就不谈堆栈操作了理解图就行了),然后各种变量会垃圾回收,而这里parent函数确实销毁了,但是firstName这个参数并没有垃圾回收,释放内存,依然在内存中能够被return里面的函数使用,好像return里面的函数把 父函数的那个资源给关闭在了自己的函数里面一样,这个函数销毁资源被关闭到子函数中依然能够使用的现象叫做闭包。
注意匿名函数自执行只是产生闭包的一种情况,闭包是现象或者情形,不实用匿名函数自执行也有很多情况产生闭包,所以而且根本就是两回事儿,不能混淆。
类比,在window系统中,你子文件夹中有使用的文件父文件夹是没法删除的。
与这个类似的一个题是循环里面用事件,事件里面的i有问题 ,如下。
还有一到非常爱考的面试题,
我只分析一个,其它的大家就会分析了。注意表象上粗略的理解就是 函数执行一瞬间,并不会等定时器,但是这个说法并不对,因为第一个就说不通。好我给记大家进入内部深入分析下过程。
小测验,你能看出下面的程序用了闭包吗?
3.闭包在jquery中使用。
闭包无处不在,直接看jquery的例子。
写一个回调函数,通过回调方法返回值,function ajaxUser(function(val){ console.log(val);}){ ... }
jquery是一个轻量级的JS框架,这点相信大部分人都听过,而jquery之所以有这样一个称呼,就是因为它悄悄披了一件外衣,将自己给隐藏了起来。
//以下截取自jquery源码片段(function( window, undefined ) { /* 源码内容 */})( window );
上面这一小段代码来自于1.9.0当中jquery的源码,它是一个无污染的JS插件的标准写法,专业名词叫闭包。可以把它简单的看做是一个函数,与普通函数不同的是,这个函数没有名字,而且会立即执行,就像下面这样,会直接弹出字符串。
(function( window, undefined ) {
alert("Hello World!");
})( window );
可以看出来这样写的直接效果,就相当于我们直接弹出一个字符串。但是不同的是,我们将里面的变量变成了局域变量,这不仅可以提高运行速度,更重要的是我们在引用jquery的JS文件时,不会因为jquery当中的变量太多,而与其它的JS框架的变量命名产生冲突。对于这一点,我们拿以下这一小段代码来说明。
var temp = "Hello World!";
(function( window, undefined ) { var temp = "ByeBye World!";
})( window );
alert(temp);
这段代码的运行结果是Hello而不是ByeBye,也就是说闭包中的变量声明没有污染到外面的全局变量,倘若我们去掉闭包,则最终的结果会是ByeBye,就像下面这样。
var temp = "Hello World!";// (function( window, undefined ) {
var temp = "ByeBye World!";// })( window );
alert(temp);
由此就可以看出来,jquery的外衣就是这一层闭包,它是很重要的一个内容,是编写JS框架必须知道的知识,它可以帮助我们隐藏我们的临时变量,降低污染。
(function( window, undefined ) {
// Use the correct document accordingly with window argument (sandbox)
var document = window.document,
navigator = window.navigator,
location = window.location;
var jQuery = (function() { //第一个jQuery的作用是什么呢?是要给外面用的jQuery对象
// Define a local copy of jQuery
var jQuery = function( ) { //为什么又要一个jQuery?这是一个局部变量
// The jQuery object is actually just the init constructor 'enhanced'
return new jQuery.fn.init( ); //怎么才能保证程序执行这个代码呢?顺序执行下来就会执行这个代码
},
//...
;
jQuery.fn = jQuery.prototype = {
constructor: jQuery,
init: function( selector, context, rootjQuery ) {
//...
return jQuery.makeArray( selector, this );
},
//...
};
// Give the init function the jQuery prototype for later instantiation
jQuery.fn.init.prototype = jQuery.fn; //这段代码的作用是什么呢?为以后的实例准备jQuery原型构造函数
//jQuery.fn.init 是构造函数, 它的实例方法由 jQuery.fn.init.prototype 指定
//...很多函数
return jQuery; //为什么要增加一个返回值呢?为了把局部变量复制给外面的全局变量
})();
// Expose jQuery to the global object
window.jQuery = window.$ = jQuery;
})(window);
闭包就是能够读取其他函数内部变量的函数。由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成"定义在一个函数内部的函数"。所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。
扩展资料:
闭包包含自由(未绑定到特定对象)变量;这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义(局部变量)。
"闭包" 一词来源于以下两者的结合:要执行的代码块(由于自由变量被包含在代码块中,这些自由变量以及它们引用的对象没有被释放)和为自由变量提供绑定的计算环境(作用域)。在PHP、Scala、Scheme、Common Lisp、Smalltalk、Groovy、JavaScript、Ruby、 Python、Go、Lua、objective c、swift 以及Java(Java8及以上)等语言中都能找到对闭包不同程度的支持。