理解閉包
阿新 • • 發佈:2018-09-25
out col 設置 n) return 參數 console div 面向對象
閉包是創建一個函數的時候允許在這函數裏可以訪問並且操作函數之外的變量所創建的作用域。
隨處可見的閉包
var name = ‘cher‘; //一個全局變量 function fn() { //聲明一個全局函數 console.log(name); //cher 在這個函數裏面訪問外面的全局變量 } fn();//在這函數裏面可以訪問到函數外的變量形成了簡單的閉包
一個神奇的閉包
var name = ‘cher‘; //創建一個全局變量 var innerFn; function outFnHandler() { //創建一個全局函數 var outname = ‘xiaoming‘; //全局函數下的一個變量 function innerFnHandler() { //一個內部函數 console.log(name); //cher console.log(outname); // xiaoming } innerFn = innerFnHandler; } outFnHandler(); //執行這個全局函數的時候,把內部函數放到innerFn變量上 innerFn(); //在執行這個內部函數,必須要執行完全局函數後才能執行innerFn函數
在這裏outFnHandler已經執行完畢,作用域不在了,為什麽內部函數還可以訪問到outname變量?
因為閉包,創建innerFnHandler的時候也創建了一個閉包,閉包裏包含了這個聲明的函數,還包含了這個聲明的函數作用域下的所有變量,
所有即使作用域消失,但是通過閉包還是可以訪問outname
看看那些東西是閉包可以訪問的
var name = ‘cher‘; //創建一個全局變量 var innerFn; function outFnHandler() { //創建一個全局函數 var outname = ‘xiaoming‘; //全局函數下的一個變量 function innerFnHandler(age) { //一個內部函數 console.log(name); //cher console.log(outname); // xiaoming console.log(age); //7 console.log(sex); //男 } innerFn = innerFnHandler; } console.log(sex); //undefined var sex = ‘男‘; outFnHandler(); //執行這個全局函數的時候,把內部函數放到innerFn變量上 innerFn(7); //傳遞一個實參給內部函數
這裏可以看得出給內部函數傳遞一個參數過去是可以訪問的,作用域之外的所有變量不管前後都是可以訪問的,所有可以訪問到sex
閉包的作用
1、可以封裝一些東西作用私有變量
function Fn() { //聲明一個構造器 var name = 0; //構造器裏有一個變量name this.getName = function () { //創建一個獲取這個name變量的方法 return name; } this.setName = function () { // 創建一個設置name變量的方法 name++ ; } } var fn = new Fn(); fn.setName(); //這樣就只能通過setName來設置這個變量 console.log(fn.getName()); //用getName 來獲取這個變量
在這裏我們就只能通過構造器的倆個方法來獲取或者設置構造器裏的變量,就像面向對象語言裏面的私有變量了。
2、回調
回調函數是一個在需要的時候可以執行的一種函數,回調函數就是一個閉包,通常回調函數就會訪問外面的閉包
function outFn(fn) { //創建一個全局函數 var name = ‘cher‘; //在這個全局函數裏創建一個變量name console.log(name); //cher fn(name); //使用回調可以訪問這個全局函數裏的變量name } outFn(function (sex) { console.log(sex); //cher });
在這裏的回調就可以訪問外部的變量,也避免了使用全局變量
理解閉包