作用域和閉包-執行上下文: 變數提升(寫代碼時千萬不要先使用再定義) <script> console.log(a);//undefined var a=10; fn('cyy',18); function fn(name,age){ age=20; console.log(name,age);// ...
作用域和閉包-執行上下文:
變數提升(寫代碼時千萬不要先使用再定義)
<script> console.log(a);//undefined var a=10; fn('cyy',18); function fn(name,age){ age=20; console.log(name,age);//cyy 20 var age; } </script>
函數聲明存在提升,函數表達式不存在提升
<script> fn1();//函數聲明 不會報錯 function fn1(){} fn2();//函數表達式 報錯 var fn2=function(){} </script>
<script> fn('cyy'); function fn(name){ console.log(this); console.log(arguments); console.log(name); } </script>
作用域和閉包-this:
this要在執行時才能確認值,定義時無法確認
<script> var a={ name:'cyy', fn(){ console.log(this.name); } } a.fn();//this===a a.fn.call({name:'cyy2'});//this==={name:'cyy2'} var fn1=a.fn; fn1();//this===window </script>
this:
作為構造函數執行
作為對象屬性執行
作為普通函數執行
call apply bind
<script> //構造函數 function Foo(name){ this.name=name; } var f=new Foo('cyy'); //作為一個對象的屬性 var obj={ name:'cyy', fn(){ console.log(this.name); } } obj.fn(); //普通函數的this function fn(){ console.log(this); } fn();//this===window //call apply bind function fn1(name,age){ console.log(name); console.log(this); } fn1.call({x:10},'cyy2',18); fn1.apply({x:20},['cyy3',19]); var fn2=function(name,age){ console.log(name); console.log(this); }.bind({x:30}); fn2('cyy4',20); </script>
作用域和閉包-作用域:
沒有塊級作用域,只有函數和全局作用域
<script> //無塊級作用域 if(true){ var name='cyy'; } console.log(name); //有全局和函數作用域 var a=10; function fn(){ var a=20; console.log('fn:'+a); } fn(); console.log('global:'+a); </script>
<script> //作用域鏈 var a=10; function fn(){ var b=20; //當前函數作用域內沒有定義的變數,即自由變數 console.log(a); console.log(b); } fn(); </script>
作用域和閉包--閉包:
閉包的使用場景:
1、函數作為返回值
2、函數作為參數傳遞
<script> //函數作為返回值 function F1(){ var a=100; return function(){ console.log(a);//a是自由變數,向父級作用域去尋找---函數定義時的作用域 } } var f1=F1(); var a=200; f1();//100 //函數作為參數傳遞 function F2(){ var b=100; return function(){ console.log(b);//b是自由變數,向父級作用域去尋找---函數定義時的作用域 } } var f2=F2(); function F3(fn){ var b=300; fn(); } F3(f2);//100 </script>
作用域和閉包--解題:
<script> //錯誤的寫法 //點擊結果都是10 var i; for(i=0;i<10;i++){ var a=document.createElement('a'); a.innerHTML=i; a.addEventListener('click',function(e){ e.preventDefault(); alert(i);//i是自由變數,要去父作用域尋找值;for迴圈不是作用域,所以獲取到的i是迴圈結束的全局變數i=10 }) document.body.appendChild(a); } //正確寫法,自執行的匿名函數形成函數作用域 var i; for(i=0;i<10;i++){ (function(i){ //形成函數作用域,i不再是全局變數 var a=document.createElement('a'); a.innerHTML=i; a.addEventListener('click',function(e){ e.preventDefault(); alert(i);//i是自由變數,要去父作用域尋找值 }) document.body.appendChild(a); })(i); } </script>
<script> //閉包的應用 function isFirstLoad(){ var _list=[];//通常_開頭的變數表示私有 return function(id){ if(_list.indexOf(id) >= 0){//不是第一次出現 return false; }else{ _list.push(id); return true; } } } var firstload=isFirstLoad(); console.log(firstload(10));//true console.log(firstload(10));//false console.log(firstload(20));//true </script>