1.做用域閉包
執行上下文 (變量提早、函數聲明提早、肯定this值、arguments)app
範圍:一段<script>或者一個函數(都會生成一個執行上下文) 全局(一段<script>):變量定義、函數聲明 函數:變量定義、函數聲明、this、arguments(參數集合)
變量提早代碼解析:函數
consol.log(a) //undefined var a = 100 (執行過程:(1)變量定義提早 var a = undefined (2)consol.log(a) //undefined (3)a = 100 //賦值 )
函數聲明提早代碼解析:this
函數聲明:function fn(){} 函數表達式:var fn = function(){} fn() function fn(){} (執行過程:(1)function fn(){} (2)fn() ) fn() var fn = function(){} (執行過程:(1)var fn = undefined (2)fn() (3)fn = function(){} )
this (執行時才能確認,定義時沒法確認)code
this執行場景: (1)做爲構造函數執行 function Foo(name){ // this = {} this.name = name // returen this } var fn = new Foo("lala") (2)做爲對象屬性執行 var obj = { name:"lala", printName: function(){ console.log(this.name) } } obj.printName();// 對象屬性執行,this就是對象obj (3)做爲普通函數執行 function fn(){ console.log(this) // window } (4)call、apply、bind function fn(name,age){ alert(name) console.log(this) //{x:100} } fn.call({x:100},"lala",13) //{x:100}當this fn.apply({x:100},["lala",13]) var fn = function fn(name,age){ alert(name) console.log(this) // }.bind({x:100}) //函數表達式.bind fn("lala",13)
做用域 JS沒有塊級做用域,只有函數和全局做用域對象
(1)無塊級做用域 if(true){ var a = 10 } console.log(name) //name (2)函數做用域和全局做用域 var a = 10 //全局做用域(均可以訪問獲取) function fn(){ var a = 20 console.log(a) // 20 函數做用域(從外面得不到,也改不了) } console.log(a) //10 fn()
2.做用域鏈ip
自由變量:當前做用域沒有定義的變量 函數父級做用域:函數定義時的做用域(函數在哪定義,父級做用域在哪) var a = 10 function fn1(){ var b = 20 function fn2(){ var c = 30 console.log(a) //10 a是自由變量 console.log(b) //20 b是自由變量 console.log(c) } fn2() } fn1() 做用域鏈:自由變量不斷向父級做用域中尋找,造成鏈式
3.閉包
應用場景:(1)函數做爲返回值作用域
function fn(){ var a = 10 return function(){ console.log(a) //10 } } var f1 = fn() var a = 20 f1()
(2)函數做爲參數傳遞(函數傳遞到另外一個函數中執行)開發
function fn(){ var a = 10 return function(){ console.log(a) //10 } } var f1 = fn() function f2(f){ var a = 20 f() } f2(f1)
相關問題:io
1.理解變量提高 變量定義、函數聲明被提高(到包含他們做用域的最頂端) 2.建立10個a標籤,點擊時彈出對應的序號 var i for(i = 0; i < 10; i++){ (function(i){ var a = document.creatElement("a") a.innerHtml = i a.addEventListerner("click",function(e){ e.preventDefault() alert(i) }) document.body.appendChild(a) })() } 3.實際開發中閉包的應用:封裝變量,收斂權限 function isFirst(num){ var _list = [] // _list 下劃線表示私有的 return function(){ if(_list.indexOf(num)){ return false }else{ _list.push(num) return true } } } var first = isFirst() first(10) // true first(10) // false first(20) // true