搜索
您的当前位置:首页正文

javascript匿名函数的理解(透彻版)_javascript技巧

2023-12-02 来源:优库美食网

代码如下: (function(){ //这里忽略jQuery所有实现 })(); (function(){ //这里忽略jQuery所有实现 })();   半年前初次接触jQuery的时候,我也像其他人一样很兴奋地想看看源码是什么样的。然而,在看到源码的第一眼,我就迷糊了。为什么只有一个匿 名函数又没看到运行(当然是运行了……),就能有jQuery这么个函数库了?于是,我抱着疑问来到CSDN。结果相信现在很多人都很清楚了(因为在我之 后也不乏来者,呵呵~)。当一个匿名函数被括起来,然后再在后面加一个括号,这个匿名函数就能立即运行起来!真神奇哦!   嘿嘿!胡闹到此为止。在这一节,我们碰到的jQuery片段是一组立即运行的匿名函数。而这种用法在论坛上也曾引起过激辩——这段代码究竟属不 属于闭包呢?带着这个疑问,我们从基础开始,分析每个关键要素,寻找属于自己的答案。(没错,自己的答案!在我看来,所有理论只是形式,只要它有利于我们 的应用实现,就是可取的——黑猫白猫,抓到老鼠的就是好猫!)   要说匿名函数,我们首先要由函数本身说起。函数的定义如下: 函数是将唯一的输出值赋予给每一输入的“法则”。   当然,这只是数学上的定义。但是,在计算机编程语言中,函数的定义也八九不离十。因为,我们都知道,计算机中的函数,也类似数学定义中的描述,它是将输入的若干数据,经过代码设定的逻辑操作处理后,返回唯一的输出的一组代码组合块。——当然,特例是,输入的数据为空或输出的数据为空,或者两者都为空。   下面,我们先初步了解一下和匿名函数相关的概念。 函数声明(function 语句)   要使用一个函数,我们就得首先声明它的存在。而我们最常用的方式就是使用function语句来定义一个函数,如: 代码如下: function abc(){ // code to process } function abc(){ // code to process }   当然,你的函数也可以是带参数的,甚至是带返回值的。 view plaincopy to clipboardprint? function abc(x,y){ return x+y; } function abc(x,y){ return x+y; }   但是,无论你怎么去定义你的函数,JS解释器都会把它翻译成一个Function对象。例如,你在定义上面的其中一个例子的函数号,再输入如下代码: alert(typeof abc);// "function"   你的浏览器就会弹出提示框,提示你abc是一个Function对象。那么Function对象究竟是什么呢? Function 对象   Function对象是JavaScript里面的固有对象,所有的函数实际上都是一个Function对象。关于这个方面的讨论,我们留到下一个专题节。我们先看看,Function对象能不能直接运用构造函数创建一个新的函数呢?答案是肯定的。例如: 代码如下: var abc = new Function("x","y","return x*y;"); alert(abc(2,3)); // "6" var abc = new Function("x","y","return x*y;"); alert(abc(2,3)); // "6"   相信大家现在对如何声明一个函数应该是有所了解了。那么什么才是匿名函数呢? 声明匿名函数   顾名思义,匿名函数就是没有实际名字的函数。例如,我们把上面的例子中,函数的名字去掉,再判断一下他是不是一个函数: 代码如下: alert(typeof function(){});// "function" alert(typeof function(x,y){return x+y;});// "function" alert(typeof new Function("x","y","return x*y;"))// "function" alert(typeof function(){});// "function" alert(typeof function(x,y){return x+y;});// "function" alert(typeof new Function("x","y","return x*y;"))// "function"   我们可以很容易地看到,它们全都是Function对象,换言之,他们都是函数,但是他们都有一个特点——没有名字。所以我们把他们称作“匿名函数”。然而,正因为他们没有“名字”,我们也没有办法找到他们。这就引申了如何去调用一个匿名函数的问题了。 匿名函数的调用   要调用一个函数,我们必须要有方法定位它,引用它。所以,我们会需要帮它找一个名字。例如: 代码如下: var abc=function(x,y){ return x+y; } alert(abc(2,3)); // "5" var abc=function(x,y){ return x+y; } alert(abc(2,3)); // "5"   上面的操作其实就等于换个方式去定义函数,这种用法是我们比较频繁遇到的。例如我们在设定一个DOM元素事件处理函数的时候,我们通常都不会为他们定名字,而是赋予它的对应事件引用一个匿名函数。   对匿名函数的调用其实还有一种做法,也就是我们看到的jQuery片段——使用()将匿名函数括起来,然后后面再加一对小括号(包含参数列表)。我们再看一下以下例子: 代码如下: alert((function(x,y){return x+y;})(2,3));// "5" alert((new Function("x","y","return x*y;"))(2,3));// "6" alert((function(x,y){return x+y;})(2,3));// "5" alert((new Function("x","y","return x*y;"))(2,3));// "6"   很多人或许会奇怪,为什么这种方法能成功调用呢?觉得这个应用奇怪的人就看一下我以下这段解释吧。   大家知道小括号的作用吗?小括号能把我们的表达式组合分块,并且每一块,也就是每一对小括号,都有一个返回值。这个返回值实际上也就是小括号中表达式的返回值。所以,当我们用一对小括号把匿名函数括起来的时候,实际上小括号对返回的,就是一个匿名函数的Function对象。因此,小括号对加上匿名函数就如同有名字的函数般被我们取得它的引用位置了。所以如果在这个引用变量后面再加上参数列表,就会实现普通函数的调用形式。   不知道以上的文字表述大家能不能看明白,如果还是理解不了的话,再看一下以下的代码试试吧。 代码如下: var abc=function(x,y){return x+y;};// 把匿名函数对象赋给abc // abc的constructor就和匿名函数的constructor一样了。也就是说,两个函数的实现是一样的。 alert((abc).constructor==(function(x,y){return x+y;}).constructor); var abc=function(x,y){return x+y;};// 把匿名函数对象赋给abc // abc的constructor就和匿名函数的constructor一样了。也就是说,两个函数的实现是一样的。 alert((abc).constructor==(function(x,y){return x+y;}).constructor);   PS:constructor是指创建对象的函数。也就是函数对象所代表的函数体。   总之,将其(被小括号包含的匿名函数)理解为括号表达式返回的函数对象,然后就可以对这个函数对象作正常的参数列表调用了。(前面这里犯了个错 误,只有函数表达式还是不能直接调用函数的,去掉匿名函数括号必须要伴随将表达式赋值。也就是(function(){alert(1)})()应该是与 a=function(){alert(1)}()等价,不能连a=都去掉。) 闭包   闭包是什么?闭包是指某种程序语言中的代码块允许一级函数存在并且在一级函数中所定义的自由变量能不被释放,直到一级函数被释放前,一级函数外也能应用这些未释放的自由变量。   怎样?看得一头冒汗吧……没事,我也是(虽然是我是了解的,只是表达能力的问题)。让我们换个更加简单的方法说明:闭包,其实是一种语言特性,它是指的是程序设计语言中,允许将函数看作对象,然后能像在对象中的操作搬在函数中定义实例(局部)变量,而这些变量能在函数中保存到函数的实例对象销毁为止,其它代码块能通过某种方式获取这些实例(局部)变量的值并进行应用扩展。   不知道这么再解释后会否更加清晰,如果还是不明白,那么我们再简化一下:闭包,其实就是指程序语言中能让代码调用已运行的函数中所定义的局部变量。   现在我们看一个例子: 代码如下: var abc=function(y){ var x=y;// 这个是局部变量 return function(){ alert(x++);// 就是这里调用了闭包特性中的一级函数局部变量的x,并对它进行操作 alert(y--);// 引用的参数变量也是自由变量 }}(5);// 初始化 abc();// "5" "5" abc();// "6" "4" abc();// "7" "3" alert(x);// 报错!“x”未定义! var abc=function(y){ var x=y;// 这个是局部变量 return function(){ alert(x++);// 就是这里调用了闭包特性中的一级函数局部变量的x,并对它进行操作 alert(y--);// 引用的参数变量也是自由变量 }}(5);// 初始化 abc();// "5" "5" abc();// "6" "4" abc();// "7" "3" alert(x);// 报错!“x”未定义!   看到这里,你能判断究竟jQuery的那个代码片段是否闭包了吗?   以我的理解来说吧。是否应用了闭包特性,必须确定该段代码有没有 最重要的要素:未销毁的局部变量。那么很显然,没有任何实现的匿名函数不可能应用了闭包特性。但如果匿名函数里面有实现呢?那也还得确定它的实现中有没有 用到那些未销毁的局部变量。所以如果问你那个开篇中的jQuery代码片段是应用了JS里的什么特性?那么它只是匿名函数与匿名函数的调用而已。但是,它 隐含了闭包的特性,并且随时可以实现闭包应用。因为JS天生就是有这个特性的!(这只是我的理解,我也想知道你的理解,欢迎交流!关于闭包,有机会还是独立再开一个专题吧!)

小编还为您整理了以下内容,可能对您也有帮助:

讲解Javascript中什么是匿名函数

本文给大家介绍Javascript中什么是匿名函数 ,有一定的参考价值,有需要的朋友可以参考一下,希望对你们有所帮助。

分析:

1、所谓匿名函数,从字面意思理解,就是没有名字的函数,js 用()来代替(注意,是英文状态下的括号)

2、定义形式:

function (){

//to add codes that you want to add

}3、匿名函数作用

(1)与闭包函数相比较,最大作用是不污染全局对象,一旦执行完毕,GC自动回收内存,这是与闭包函数本质的区别。闭包函数的一大特点是:

变量常驻内存,只有关闭浏览器时,才释放。

function f1(){

var n=999;

nAdd=function(){n+=1}

function f2(){

alert(n);

}

return f2;

}

var result=f1();

result(); // 999

nAdd();

result(); // 1000在如上这段代码中,result实际上就是闭包f2函数。它一共运行了两次,第一次的值是999,第二次的值是1000。这证明了,函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被自动清除。

为什么会这样呢?原因就在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。

这段代码中另一个值得注意的地方,就是“nAdd=function(){n+=1}”这一行,首先在nAdd前面没有使用var关键字,因此 nAdd是一个全局变量,而不是局部变量。其次,nAdd的值是一个匿名函数(anonymous function),而这个

匿名函数本身也是一个闭包,所以nAdd相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作。

(2)与一般函数相比较,不执行预编译。

function fuc() {

fuc1(); //foo被提到了作用域的最前面, 于是这里可以正常调用foo函数

fuc2(); //这里会报错bar是个undefined

function fuc1() {alert("foo()") }

var fuc2 = function () { alert("bar")};

}Code:

匿名函数的几种表现形式:

模式一:函数字面量 (Function Literal)

先声明函数对象,然后执行。

(function(){

// insert code here

})();模式二:优先表达式 (Prior Expression)

由于 JavaScript 按照从内到外的顺序执行表达式,因此使用括号来强制执行已声明的函数。

(function(){

// insert code here

}()); 模式三:Void 操作符 (Void Operator)

使用 Void 操作符执行一个单独的操作数。

void function(){

// insert code here

}();总结:

javascript中: (function(){})();如何理解?

javascript中: (function(){})()是匿名函数,主要利用函数内的变量作用域,避免产生全局变量,影响整体页面环境,增加代码的兼容性。

(function(){})是一个标准的函数定义,但是没有复制给任何变量。所以是没有名字的函数,叫匿名函数。没有名字就无法像普通函数那样随时随地调用了,所以在他定义完成后就马上调用他,后面的括号()是运行这个函数的意思

扩展资料

函数声明:使用function声明函数,并指定函数名。 

function setFn() {    // coding   }

函数表达式:使用function声明函数,但未指定函数名,将匿名函数赋予一个变量。

var setFn = function() {    // coding}

匿名函数:使用function关键字声明函数,但未指定函数名。匿名函数属于函数表达式,匿名函数有很多作用,赋予一个变量则创建函数,赋予一个事件则成为事件处理程序或创建闭包等等。

function() {    // coding}

参考资料:百度百科 - javascript

JS匿名函数应该怎样使用

这次给大家带来JS匿名函数应该怎样使用,使用JS匿名函数的注意事项有哪些,下面就是实战案例,一起来看一下。

匿名函数的基本形式为(function(){...})();

前面的括号包含函数体,后面的括号就是给匿名函数传递参数并立即执行之

匿名函数的作用是避免全局变量的污染以及函数名的冲突

无论你在什么时候读代码,您都必须注意到匿名函数。有时它们被称为 lambda,有时是匿名函数,不管怎样,我认为他们是不好使用的。

如果你不知道匿名函数是什么,这里有一个引语:

匿名函数是一种在运行时动态声明的函数。它们之所以被称为匿名函数是因为不同于普通函数,它们并没有函数名 。 — Helen Emerson, Helephant.com

匿名函数形式如下:

function () { ... code ... }

OR

(args) => { ... code .. }

我今天尝试让大家理解通常情况下只有在绝对需要的情况下才使用匿名函数的想法。匿名函数不应该是首选,而且应该知道原因情况下使用。当理解这种想法之后,你的代码会变得更简洁,更容易维护,并且更容易跟踪bug。先从避免使用匿名函数的三个理由开始:

你写代码的时候, 无论你多么擅长敲代码, 总是会碰到错误。有时候,这些错误很容易被查出,有时候并不容易。

如果你知道这些错误来自哪里,那么错误很容易会被查出来。为了查出错误,我们使用这个被叫做堆栈轨迹的工具。如果你不了解 堆栈轨迹 ,goole给出了很棒的介绍。

假设现在有一个非常简单的工程:

function start () {

(function middle () {

(function end () {

console.lg('test');

})()

})()

}

上面代码里面有一个非常愚蠢的错误,拼写错误(console.log)。在小工程里面,这个拼写错误不是什么大问题。

如果这是一个有非常多模块非常大的工程的一小段,问题就大了。假设这个愚蠢的错误不是你犯的,那么新来的初级工程师将会在他休假之前把这个错误提交到代码库!

现在,我们必须追查。 使用我们精心命名的函数, 我们得到如下的堆栈跟踪:

谢谢你命名你的函数 ,初级开发者们! 现在我们可以轻松地追踪到这个bug。

但是..一旦我们解决了这个问题, 就会发现 还有另一个bug。 这次是一位更资深的开发人员介绍的。这个人知道 lambdas

结果他们偶然发现了一个bug,我们的工作就是追踪它。

下面是代码:

(function () {

(function () {

(function () {

console.lg('test');

})();

})();

})();

吃不吃惊,这名开发者也忘记了如何拼写console.log了!这也太巧合了吧!令人感到遗憾的是,他们都没有命名他们的函数。

那么控制台会输出什么呢?

好吧,我们至少还有行号,对吧?在这个例子中,看起来我们有大约7行代码。如果我们处理一大段代码会如何呢?比如一万行代码?行号的跨度如此之大该怎么办呢?如果代码被折叠后有没有一个代码地图文件,那么对行号的渲染是不是根本就是没有什么用了呢?

我想对这些问题的回答相当简单,答案就是:想这些会让你一整天都会过的相当糟心。

可读性

咦,我听说你还不信。你仍旧对你的匿名函数恋恋不舍,并且还从未发生过bug。那么我得向你道歉,你认为你的代码是完美的。让我们看看这个!

看看下面两段代码:

function initiate (arguments) {

return new Promise((resolve, reject) => {

try {

if (arguments) {

return resolve(true);

}

return resolve(false);

} catch (e) {

reject(e);

}

});

}

initiate(true)

.then(res => {

if (res) {

doSomethingElse();

} else {

doSomething();

}

).catch(e => {

logError(e.message);

restartApp();

}

);

这是一个非常不正常的例子,但是我相信你已经明白我要说什么 了。我们的方法返回了一个promise,我们用这个promise对象/方法处理不同可能的 响应。

你也许会认为几段代码读起来并不难,但我认为它们可以变得更好!

如果我们去掉所有的匿名函数会怎样呢?

function initiate (arguments) {

return new Promise(checkForArguments);

}

function checkForArguments (resolve, reject) {

try {

if (arguments) {

return resolve(true);

}

return resolve(false);

} catch (e) {

reject(e);

}

}

function evaluateRes (res) {

if (res) {

doSomethingElse();

} else {

doSomething();

}

}

function handleError (e) {

logError(e.message);

restartApp();

}

initiate(true)

.then(evaluateRes)

.catch(handleError);

好,先讲清楚:这部分代码更长,但我认为其不仅仅是有更多的可读性!我们精心命名的函数与匿名函数不一样,只要我们一看到它们的名字就知道它们的功能是什么。这避免了在评估代码时的障碍。

这也有助于分清楚其中的关系。与创建一个方法、将其传递、然后运行逻辑不同,在第二个例子中的参数被给到了then,catch只是指向了发生所有事情的函数。

关于更具有可读性,我没有什么再能说服你的了。但是也许你还没被说服的话,我可以试一下最后的论据。

相信看了本文案例你已经掌握了方法,更多精彩请关注Gxl网其它相关文章!

推荐阅读:

JavaScript匿名函数和普通函数有什么区别?

匿名函数在声明时不用带上函数名, 可以把匿名函数当作一个function类型的值来对待

声明一个普通的函数 function func() { ... } 可以认为和var func = function() { ... };相同, 但是普通函数会自动把函数名"提到"作用域的最前面, 基本上普通函数和匿名函数就只有这一个区别

function xxx() {
    foo(); //foo被提到了作用域的最前面, 于是这里可以正常调用foo函数
    bar(); //这里会报错bar是个undefined

    function foo(){}
    var bar = function(){};
}

追问你最后写的那个函数想表达什么?

追答作用域

JavaScript匿名函数和普通函数有什么区别?

匿名函数在声明时不用带上函数名, 可以把匿名函数当作一个function类型的值来对待

声明一个普通的函数 function func() { ... } 可以认为和var func = function() { ... };相同, 但是普通函数会自动把函数名"提到"作用域的最前面, 基本上普通函数和匿名函数就只有这一个区别

function xxx() {
    foo(); //foo被提到了作用域的最前面, 于是这里可以正常调用foo函数
    bar(); //这里会报错bar是个undefined

    function foo(){}
    var bar = function(){};
}

追问你最后写的那个函数想表达什么?

追答作用域

javascript 匿名函数的用途到底是啥?

1 分析: 函数为何要有名字? 是为了方便下次使用. 匿名函数, 即没有名字.  

2 用途: 通常不希望再次使用(即只使用一次的)的函数可以定义为匿名函数. 

3 使用示例: 

// 定义并使用一个匿名函数来打印从1到10的整数

(function (n) {

    for (var i = 1; i <= n; i++)

        console.log(i);

})(10);

4 扩展: 当然, 如果还是想再次使用匿名函数的话, 也有方法. 即把匿名函数赋给一个变量(funtion类型的变量), 想再次使用时, 使用该变量来调用即可.示例如下: // 定义一个匿名函数并将它赋给变量printN

var printN = function (n) {

    for (var i = 1; i <= n; i++)

        console.log(i);

};

// 通过变量printN来再次使用该匿名函数

printN(10);

5 运行效果果图如下:

图1

图2

javascript中匿名函数何时用

JS中的匿名函数的用法及优缺点 匿名函数可以有效的保证在页面上写入Javascript,而不会造成全局变量的污染。 这在给一个不是很熟悉的页面增加Javascript时非常有效,也很优美。 一、什么是匿名函数? 在Javascript定义一个函数一般有如下三种方式: 函数关键字(function)语句: function fnMethodName(x){alert(x);} 函数字面量(Function Literals): var fnMethodName = function(x){alert(x);} Function()构造函数: var fnMethodName = new Function('x','alert(x);') 上面三种方法定义了同一个方法函数fnMethodName, 第1种就是最常用的方法,后两种都是把一个函数复制给变量fnMethodName,而这个函数是没有名字的,即匿名函数。 实际上,相当多的语言都有匿名函数。 二、函数字面量和Function()构造函数的区别 虽然函数字面量是一个匿名函数,但语法允许为其指定任意一个函数名,当写递归函数时可以调用它自己,使用Function()构造函数则不行。

javascript中匿名函数何时用

JS中的匿名函数的用法及优缺点 匿名函数可以有效的保证在页面上写入Javascript,而不会造成全局变量的污染。 这在给一个不是很熟悉的页面增加Javascript时非常有效,也很优美。 一、什么是匿名函数? 在Javascript定义一个函数一般有如下三种方式: 函数关键字(function)语句: function fnMethodName(x){alert(x);} 函数字面量(Function Literals): var fnMethodName = function(x){alert(x);} Function()构造函数: var fnMethodName = new Function('x','alert(x);') 上面三种方法定义了同一个方法函数fnMethodName, 第1种就是最常用的方法,后两种都是把一个函数复制给变量fnMethodName,而这个函数是没有名字的,即匿名函数。 实际上,相当多的语言都有匿名函数。 二、函数字面量和Function()构造函数的区别 虽然函数字面量是一个匿名函数,但语法允许为其指定任意一个函数名,当写递归函数时可以调用它自己,使用Function()构造函数则不行。

javascript匿名函数

Javascript是一avascript是一种由Netscape的LiveScript发展而来的原型化继承的面向对象的动态类型的区分大小写的客户端脚本语言,主要目的是为了解决服务器终端语言,比如Perl,遗留的速度问题。当时服务端需要对数据进行验证,由于网络速度相当缓慢,只有28.8kbps,验证步骤浪费的时间太多。于是Netscape的浏览器Navigator加入了Javascript,提供了数据验证的基本功能。所以,JavaScript 被数百万计的网页用来改进设计、验证表单、检测浏览器、创建cookies,以及更多的应用。
JavaScript函数是命名的语句段,这个语句段可以被当作一个整体来引用和执行。
使用函数要注意以下几点:
1)函数由关键字function定义(也可由Function构造函数构造)
2)使用function关键字定义的函数在一个作用域内是可以在任意处调用的(包括定义函数的语句前);而用var关键字定义的必须定义后才能被调用
3)函数名是调用函数时引用的名称,它对大小写是敏感的,调用函数时不可写错函数名
4)参数表示传递给函数使用或操作的值,它可以是常量,也可以是变量,也可以是函数,在函数内部可以通过arguments对象(arguments对象是一个伪数组,属性callee引用被调用的函数)访问所有参数
5)return语句用于返回表达式的值。
6)yield语句扔出一个表达式,并且中断函数执行直到下一次调用next。

javascript匿名函数

Javascript是一avascript是一种由Netscape的LiveScript发展而来的原型化继承的面向对象的动态类型的区分大小写的客户端脚本语言,主要目的是为了解决服务器终端语言,比如Perl,遗留的速度问题。当时服务端需要对数据进行验证,由于网络速度相当缓慢,只有28.8kbps,验证步骤浪费的时间太多。于是Netscape的浏览器Navigator加入了Javascript,提供了数据验证的基本功能。所以,JavaScript 被数百万计的网页用来改进设计、验证表单、检测浏览器、创建cookies,以及更多的应用。
JavaScript函数是命名的语句段,这个语句段可以被当作一个整体来引用和执行。
使用函数要注意以下几点:
1)函数由关键字function定义(也可由Function构造函数构造)
2)使用function关键字定义的函数在一个作用域内是可以在任意处调用的(包括定义函数的语句前);而用var关键字定义的必须定义后才能被调用
3)函数名是调用函数时引用的名称,它对大小写是敏感的,调用函数时不可写错函数名
4)参数表示传递给函数使用或操作的值,它可以是常量,也可以是变量,也可以是函数,在函数内部可以通过arguments对象(arguments对象是一个伪数组,属性callee引用被调用的函数)访问所有参数
5)return语句用于返回表达式的值。
6)yield语句扔出一个表达式,并且中断函数执行直到下一次调用next。

匿名函数、嵌套函数、闭包分别是什么

匿名函数: 之前的文章也有讲到,指的是 没有函数名的函数

function (){

console.log('匿名函数')

}嵌套函数呢 ? 请看代码:

function test (){

var sum = 20;

//内嵌函数

demo = function(){

alert(sum);

console.log('我是嵌套函数');

}

}如代码所示,函数内部嵌入函数,称之为嵌套函数。

那闭包又是什么呢?

不多说,看代码

function demo(){

var num = 0;

// 返回一个函数

return function(){

alert( num+1 );

}

}

//将返回的函数赋值给 add 变量

var add = demo();

// add就是一个闭包

add();这么看,感觉像是,只要是嵌套函数,且能访问上一层作用域的变量就是闭包。 是这样吗?

我们知道,js中,分为全局作用域,局部作用域,每个函数也就相等于一个局部作用域。

同理,变量,也分为全局变量和局部变量。 有什么区别呢?

在浏览器中,全局作用域对象是 window,也就是说页面一打开,window对象就存在。

在js中,每个函数是局部作用域,局部变量会随着 函数的执行创建和执行完毕后销毁。

而全局变量,只要页面不关闭,则会一直存在。并不会随着函数的执行完毕而销毁。

那么和闭包有什么关系呢?

在 “javaScript高级程序” 这本书有讲到过“作用域链”的概念, 特殊之处,在于函数内部可以直接读取全局变量。

而函数外部却不能读取函数内部的变量。

也就是说,作用域链就像只能往上不能往下的阶梯。我们看段代码理解

var name = "window";

var age = 20;

dmeo();

function demo(){

var age = 21;

console.log(name); // window

console.log(age); //21

}在执行 demo() 函数时,就会创建一个通往全局作用域链,保存着当前作用域的变量,以便查找返回。

在执行 console.log( name ) 这段代码时,会搜寻当前作用域( demo函数 ) 中是否存在 name 变量,因当前作用域不存在,所以在往上找到全局变量 name ,因此返回 window;

在执行 console.log( age ) 这段代码时, 也会搜寻 当前作用域(demo函数) 中是否存在 age 变量,因为存在,所以返回 21。

既然机制是只能往上读, 那么考虑一个问题,怎么在外部读取内部函数的变量呢?

办法不是没有,稍微变通下即可。这就需要用到闭包的概念,

function f1(){

var num = 0 ;

//定义内部函数

function f2(){

return num + 1;

}

//返回 f2函数引用

retufn f2;

}

// bar 变量也指向 f2 函数,在此也是一个闭包

var bar = f1();

//执行

bar(); // 1;我们知道,函数中的变量会随着函数的执行完毕后会被销毁。而如上代码,f1()函数执行完毕后,将f2函数赋值给一个全局变量,而f2函数的变量又依赖f1的num变量,因此,f1

中的num变量并不会随着f1的函数执行完毕后而销毁。

这里借用 “阮一峰” 大神的题目借此解析加深理解。

链接: 学习javaScript闭包

var name = "the window";

var obj = {

name : 'the obj',

getName : function(){

return funciton(){

return this.name;

}

}

}

//执行 getName返回的函数

alert(obj.getName()()); 我们看调用函数分析, 分成两部分执行。 先来看 obj.getName(); 此时getName函数由 obj对象调用,因此this的值是 obj。 但此时并不是输出而是返回一个函数。

再加上一个(); 执行返回的函数,但此时返回的函数并没有任何对象调用,当不是对象本身调用,this的值会被提升到 window对象。因此输出的是 “the window"

var name = "the Window";

var obj = {

name : "the obj",

getName : funciton(){

var that = this;

return function(){

return that.name;

}

}

}

//执行 getName 返回的函数

alert(obj.getName()());

javascript中函数是什么意思

( function(){…} )()和( function (){…} () )是两种javascript立即执行函数的常见写法,要理解立即执行函数,需要先理解一些函数的基本概念。

函数声明:

function fnName () {…};使用function关键字声明一个函数,再指定一个函数名,叫函数声明。

函数表达式:

var fnName = function () {…};使用function关键字声明一个函数,但未给函数命名,最后将匿名函数赋予一个变量,叫函数表达式,这是最常见的函数表达式语法形式。

匿名函数:

function () {}; 使用function关键字声明一个函数,但未给函数命名,所以叫匿名函数,匿名函数属于函数表达式,匿名函数有很多作用,赋予一个变量则创建函数,赋予一个事件则成为事件处理程序或创建闭包等等。

函数声明和函数表达式不同之处在于:

一、Javascript引擎在解析javascript代码时会‘函数声明提升'(Function declaration Hoisting)当前执行环境(作用域)上的函数声明。

而函数表达式必须等到Javascirtp引擎执行到它所在行时,才会从上而下一行一行地解析函数表达式。

二、函数表达式后面可以加括号立即调用该函数,函数声明不可以,只能以fnName()形式调用。

在function前面加!、+、 -甚至是逗号等到都可以起到函数定义后立即执行的效果,而()、!、+、-、=等运算符,都将函数声明转换成函数表达式。

消除了javascript引擎识别函数表达式和函数声明的歧义,告诉javascript引擎这是一个函数表达式,不是函数声明,可以在后面加括号,并立即执行函数的代码。

扩展资料

作用:

javascript中没用私有作用域的概念,如果在多人开发的项目上,你在全局或局部作用域中声明了一些变量,可能会被其他人不小心用同名的变量给覆盖掉。

根据javascript函数作用域链的特性,可以使用这种技术可以模仿一个私有作用域,用匿名函数作为一个“容器”。

“容器”内部可以访问外部的变量,而外部环境不能访问“容器”内部的变量,所以( function(){…} )()内部定义的变量不会和外部的变量发生冲突,俗称“匿名包裹器”或“命名空间”。

JQuery使用的就是这种方法,将JQuery代码包裹在( function (window,undefined){…jquery代码…} (window)中,在全局作用域中调用JQuery代码时,可以达到保护JQuery内部变量的作用。

优库美食网还为您提供以下相关内容希望对您有帮助:

讲解Javascript中什么是匿名函数

分析: 1、所谓匿名函数,从字面意思理解,就是没有名字的函数,js 用()来代替(注意,是英文状态下的括号) 2、定义形式: function (){ //to add codes that you want to add}3、匿名函数作用(1)与闭包函数相比...

javascript中: (function(){})();如何理解?

javascript中: (function(){})()是匿名函数,主要利用函数内的变量作用域,避免产生全局变量,影响整体页面环境,增加代码的兼容性。(function(){})是一个标准的函数定义,但是没有复制给任何变量。所以是没有名字的函数,...

JavaScript匿名函数和普通函数有什么区别?

匿名函数在声明时不用带上函数名, 可以把匿名函数当作一个function类型的值来对待 声明一个普通的函数 function func() { ... } 可以认为和var func = function() { ... };相同, 但是普通函数会自动把函数名"提到"...

javascript 匿名函数的用途到底是啥?

1 分析: 函数为何要有名字? 是为了方便下次使用. 匿名函数, 即没有名字.2 用途: 通常不希望再次使用(即只使用一次的)的函数可以定义为匿名函数.3 使用示例:// 定义并使用一个匿名函数来打印从1到10的整数(function (...

匿名函数是什么意思?

表示 f 为函数句柄,@是定义句柄的运算符。f=@(x)acos(x) 相当于建立了一个函数文件:% f.mfunction y=f(x)y=acos(x);是匿名函数的意思 函数句柄的使用方法也和函数是一样的。

javascript中匿名函数何时用

一、什么是匿名函数? 在Javascript定义一个函数一般有如下三种方式: 函数关键字(function)语句: function fnMethodName(x){alert(x);} 函数字面量(Function Literals): var fnMethodName = function(x){alert(x);} ...

javascript 中“!function(){}() ” 是什么意思?

( function(){…} )()和( function (){…} () )是两种javascript立即执行函数的常见写法,要理解立即执行函数,需要先理解一些函数的基本概念。函数声明:function fnName () {…};使用function关键字声明一个函数,再...

(function($){...})(jQuery)是什么意思

1,匿名函数定义:javasript函数(arg){...},这种形式在javascript中称为匿名函数。 Arg是匿名函数的参数。2,匿名函数调用:调用函数时,括号和参数写在函数之后。由于运算符的优先级,函数本身需要使用括号,即:(...

javascript匿名函数

JavaScript函数是命名的语句段,这个语句段可以被当作一个整体来引用和执行。使用函数要注意以下几点:1)函数由关键字function定义(也可由Function构造函数构造)2)使用function关键字定义的函数在一个作用域内是可以在任意处...

javascript 的 "!function" 是什么意思?

!function跟(function(){... })();函数意义相同,叫做立即运行的匿名函数(也叫立即调用函数)。js中可以这样创建一个匿名函数:(function(){do something...})()//或 (function(){do something...}())而匿名函数...

本文如未解决您的问题请添加抖音号:51dongshi(抖音搜索懂视),直接咨询即可。

热门图文

  • 浊水半和泥的下一句是什么

    浊水半和泥的下一句:最是萧条处。诗词名称:《茅城驿》。本名:白居易。别称:诗王、诗魔。字号:字乐天号香山居士,又号醉吟先生。所处时代:唐代。民族族群:汉族。出生地:河南新郑。出生时间:772年2月28日。去世时间:846年9月8日。主要作品:《直中书省》《新亭病后独坐招李侍郎公垂》《忆江南》《家园三绝》《赋得古原草送别》等。主要成就:新乐府运动主要倡导者、写下了不少反映人民疾苦的诗篇。

  • 早苗多间草的下一句是什么

    早苗多间草的下一句:浊水半和泥。诗词名称:《茅城驿》。本名:白居易。别称:诗王、诗魔。字号:字乐天号香山居士,又号醉吟先生。所处时代:唐代。民族族群:汉族。出生地:河南新郑。出生时间:772年2月28日。去世时间:846年9月8日。主要作品:《直中书省》《新亭病后独坐招李侍郎公垂》《忆江南》《家园三绝》《赋得古原草送别》等。主要成就:新乐府运动主要倡导者、写下了不少反映人民疾苦的诗篇。

  • 村贫屋舍低的下一句是什么

    村贫屋舍低的下一句:早苗多间草。诗词名称:《茅城驿》。本名:白居易。别称:诗王、诗魔。字号:字乐天号香山居士,又号醉吟先生。所处时代:唐代。民族族群:汉族。出生地:河南新郑。出生时间:772年2月28日。去世时间:846年9月8日。主要作品:《直中书省》《新亭病后独坐招李侍郎公垂》《忆江南》《家园三绝》《赋得古原草送别》等。主要成就:新乐府运动主要倡导者、写下了不少反映人民疾苦的诗篇。

  • 地薄桑麻瘦的下一句是什么

    地薄桑麻瘦的下一句:村贫屋舍低。诗词名称:《茅城驿》。本名:白居易。别称:诗王、诗魔。字号:字乐天号香山居士,又号醉吟先生。所处时代:唐代。民族族群:汉族。出生地:河南新郑。出生时间:772年2月28日。去世时间:846年9月8日。主要作品:《直中书省》《新亭病后独坐招李侍郎公垂》《忆江南》《家园三绝》《赋得古原草送别》等。主要成就:新乐府运动主要倡导者、写下了不少反映人民疾苦的诗篇。

  • 秋日又凄凄的下一句是什么

    秋日又凄凄的下一句:地薄桑麻瘦。诗词名称:《茅城驿》。本名:白居易。别称:诗王、诗魔。字号:字乐天号香山居士,又号醉吟先生。所处时代:唐代。民族族群:汉族。出生地:河南新郑。出生时间:772年2月28日。去世时间:846年9月8日。主要作品:《直中书省》《新亭病后独坐招李侍郎公垂》《忆江南》《家园三绝》《赋得古原草送别》等。主要成就:新乐府运动主要倡导者、写下了不少反映人民疾苦的诗篇。

Top