JavaScript匿名函数与闭包机制详解

作者:半夏时间:2026-10-28 06:30:06浏览:91

本文深入解析JavaScript中匿名函数的核心用法,以jQuery源码为例说明其如何通过闭包创建独立作用域并暴露全局接口。文章进一步探讨匿名函数在插件开发中的作用域隔离原理,以及通过挂载window对象实现内外交互的技巧,最后通过对象拷贝示例展示匿名函数的即时执行特性。

1.匿名函数概述

jQuery源码中的匿名函数与闭包

初次接触匿名函数,往往是在阅读jQuery源码时。打开jQuery文件,最先映入眼帘的便是其核心结构。


代码如下:

 
(function( window, undefined ) {.......................})(window);

上述代码即为一个典型的匿名函数。其中红色标注部分为参数列表。匿名函数的主要作用是创建一个封闭的作用域,使得外部无法直接访问该作用域内的变量和方法。



既然内部变量对外不可见,jQuery是如何被外部调用的呢?这得益于jQuery匿名函数中的特定代码(蓝色部分):


代码如下:

 
(function( window, undefined ) {
// Define a local copy of jQuery
var jQuery = function( selector, context ) {
// The jQuery object is actually just the init constructor 'enhanced'
return new jQuery.fn.init( selector, context );
}, 
......... 
window.jQuery = window.$ = jQuery;
})(window);

关键在于匿名函数内部将jQuery对象赋值给了window对象。这就是为何调用时需要传递window参数的原因。因此,每次调用jQuery,实际上是在调用挂载在window上的jQuery对象。



这种设计使得jQuery能够调用其内部方法,而外部无法直接访问内部逻辑,从而保证了代码的安全性和命名空间的纯净,避免冲突。



2.接着上面的话题,关于jQuery的插件

jQuery插件开发中的匿名函数应用

以下是我编写的一个分页控件的部分代码示例:


代码如下:

 
;(function ($) {
$.fn.tabing = function (arg) {
instance = new Plugin(this, arg);
}; 
var instance = null;
function Plugin(element){
this._tabs = $(element);
this._tabli = $("a[href*='#']",this._tabs);
this._tabDiv = this._tabs.siblings().filter("div[id*='tab']");
this.init();
} 
Plugin.prototype = {
init: function(){
this._tabli.addClass("unselected");
this._tabli.eq(0).addClass("selected");
this._tabDiv.css("display","none");
this._tabDiv.eq(0).css("display","block");
this._tabli.each(function(){
$(this).bind("click",function(){
for(var i = 0;i<instance._tabDiv.length;i++){
instance._tabDiv.eq(i).css("display","none");
} 
instance._tabDiv.filter("#"+$(this).attr("href").split('#')[1]).css("display","block");
}); 
}) 
} 
} 
})(jQuery);

注意红色标注部分,jQuery插件的开发同样依赖于匿名函数。这种写法确保了每个插件拥有独立的运行环境,互不干扰。红色标注的$.fn.tabing表明,我们在插件内部将tabing方法挂载到了jQuery的fn对象上。



这样一来,外部的jQuery对象就可以直接调用tabing方法。这是插件与外部世界交互的唯一接口。



3. 说完了jquery插件对匿名函数的使用,再说一下window的匿名函数

自定义Window匿名函数与接口暴露

既然jQuery本身就是一个挂载在window上的匿名函数(如第一点所述),那么我们如何编写自己的window匿名函数呢?



关键在于在匿名函数内部建立一个与window交互的接口,例如以下代码:


代码如下:

 
(function(){
function getObjByID(id){
return document.getElementById(id);
} 
function __addClass(id,className,classValue){
$(id).style.className=classValue;
} 
window.addClass=__addClass;
})(); 

同样关注红色标注部分,通过这种方式,我们可以在匿名函数外部调用addClass(),但无法直接调用getObjByID(),实现了接口的选择性暴露。



4.匿名函数也会在解析的时候执行

匿名函数的即时执行与对象拷贝

如下示例:


代码如下:

 
function Video() { };
function Movie() { };
var _video = new Video();
_video.size = 3;
_video.toString = function () {
return "video";
}; 
_video.getName = function () {
return "VideoXXX";
}; 
var _movie = new Movie();
(function (parent, child) {
for (var ele in parent) {
if (!child[ele]) //在child不包含该属性或者方法的时候,才会拷贝parent的一份
child[ele] = parent[ele];
} 
})(_video, _movie); //匿名函数调用的方式
alert(_movie.size); //3
alert(_movie.toString()); //[object Object]
alert(_movie.getName()); //VideoXXX

三个alert均能输出结果,这证明了匿名函数在定义后会被立即执行,完成了对象的属性拷贝。

作者最新文章

相关标签: