立即執行函數(function(){})()與閉包


變量的作用域

一、在js中,變量的定義並不是以代碼塊作為作用域的,而是以函數作為作用域。也就是說,如果變量是在某個函數中定義的,那么,它在函數以外的地方是不可見的。但是,如果該變量是定義在if或者for這樣的代碼塊中,它在代碼塊之外是可見的。

二、在js中,術語“全局變量”指的是定義在所有函數之外的變量(也就是定義在全局代碼中的變量),與之相對的是“局部變量”,所指的是在某個函數中定義的變量。其中,函數內的代碼可以像訪問自己的局部變量那樣訪問全局變量,反之則不行。

立即執行函數

匿名(function(){})()

//聲明一個普通函數,函數的名字叫fn
function fn(){
    console.log("hello");
}
/*然后將函數的名字去掉即是匿名函數*/

//匿名函數,運行時會發現報錯啦!
function (){
    console.log("hello");
}

/**單獨運行一個匿名函數,由於不符合語法要求,會報錯!
 *解決方法只需要給匿名函數包裹一個括號即可,匿名函數在其它應用場景中外層括號可以省略
 */
(function (){
    //由於沒有執行該匿名函數,所以不會執行匿名函數體內的語句。
    console.log("hello");
})

//在匿名函數后面加上一個括號即可立即執行
(function (){
    console.log("hello");
})()

//若需要傳值,直接將參數寫到括號內即可
(function (str){
    console.log("hello "+str);
})("world!")

當一個匿名函數被括起來,然后再在后面加一個括號,這個匿名函數就能立即運行起來。

匿名函數的應用場景

事件
<input type="button" value="點我!" id="btn">

<script>
    //獲得按鈕元素
    var sub=document.querySelector("#btn");
    //給按鈕增加點擊事件。
    sub.onclick=function(){
        alert("當點擊按鈕時會執行到我哦!");
    }
</script>
對象
var obj={
    name:"Java",
    age:18,
    fn:function(){
        return "Program:"+this.name+"age:"+this.age;
    }
};

//調用
console.log(obj.fn());
函數表達式
//將匿名函數賦值給變量fn。
var fn=function(){
    return "賦給變量的匿名函數!";
}

//調用方式與調用普通函數一樣
console.log(fn());
回調函數
setInterval(function(){
    console.log("這是一個回調函數,每次1秒鍾會被執行一次");
},1000);
返回值
//將匿名函數作為返回值
function fn(){

    //返回匿名函數
    return function(){
        return "hello";
    }

}

//調用匿名函數
console.log(fn()());

//或用變量接收匿名函數然后用變量名調用
var box=fn();
console.log(box());

$(function(){})

$(function(){});是$(document).ready(function(){});的簡寫,相當於window.onload = function(){} ,雖然這段jquery代碼與javascript代碼在功能上可以互換,但執行的時間不一樣,前者頁面框架加載完成就執行,后者頁面中所有內容加載完成才執行。

閉包

(function(){})()不叫閉包叫立即執行函數,所謂閉包,要拆成閉和包,閉指代不想暴露給外部的數據,包指代將數據打包出去暴露給外部;之所以這么說原因在於JS的函數作用域,函數內部的變量函數外部無法訪問,這形成了閉函數外部想得到函數內部的變量,可以通過某些方法譬如通過return等語句將內部的變量暴露出去,這形成了包;因而——立即執行函數只是函數的一種調用方式,和閉包沒有必然的聯系;閉包是和作用域扯上關系的,而(function(){})()是函數聲明完就執行,只是有時想要用到閉包那么可以用(function(){})()來構成閉包,而不是(function(){})()是閉包。閉包的本質是執行完后只返回有用的數據,包內變量完全銷毀,防止全局污染

閉包本身定義比較抽象,MDN官方上解釋是:A closure is the combination of a function and the lexical environment within which that function was declared.
中文解釋是:閉包是一個函數和該函數被定義時的詞法環境的組合。

普通函數實現閉包

按照閉包起的作用來理解它:就是能在一個函數外部執行這個函數內部定義的方法,並訪問這個函數內部定義的變量。

function box(){
  var a = 10;
  function inner(){
    return a;
  }
  return inner;
}

var outer = box();  //獲取函數內部的函數
console.log(outer());//並執行這個函數,返回結果10

正常情況,box執行過后,會被回收機制回收所占用的內存,包括其內部定義的局部變量。但是此時box執行過后返回一個內部的函數inner,這個inner引用了內部的變量a,inner又被外部outer給接收,回收機制檢查到內部的變量被引用,就不會執行回收。

  • 這個案例中用到的閉包其實是inner和inner被定義時的詞法環境,這個閉包被return出來后被外部的outer引用,因此可以在box外部執行這個inner,inner能夠讀取到box內部的變量a。

  • 使用這個閉包的目的是為了在box外部訪問a,就是通過執行outer()。

匿名函數實現閉包

//1.把內部inner這個具名函數改為匿名函數並直接return
function box(){
  var a = 10;
  return function(){
    console.log(a) ; 
  }
}

var outer = box();
outer();//10

//2.把外部var outer = box()改成立即執行的匿名函數
var outer = (function(){
  var a=10;
  return function(){
    console.log(a);
  }
})();
//outer作為立即執行匿名函數執行結果的一個接收,這個執行結果是閉包,outer等於這個閉包。
//執行outer就相當於執行了匿名函數內部return的閉包函數
//這個閉包函數可以訪問到匿名函數內部的私有變量a,所以打印出10
outer();//10

 

————————————————
參考:https://blog.csdn.net/qq_36189935/article/details/85275404
參考:https://www.jianshu.com/p/0a3150afb7ed


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM