變量的作用域
一、在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