apply和call均可以改變this的指向
函數的調用,改變this的指向
函數名字.apply(對象,[參數1,參數2,.....])
方法名字.apply(對象,[參數1,參數2,.....])
方法名字.call(對象,參數1,參數2,.....)
方法名字.call(對象,參數1,參數2,.....)
不一樣的地方:參數傳遞是方式不同
只要是想使用別的對象的方法,而且但願這個方法是當前對象的,那麼久可使用apply或者call的方法改變this的指向
apply和call方法實際上並不在函數這個實例對象彙總,而是在Function的prototype中html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script> /* apply和call均可以改變this的指向 函數的調用,改變this的指向 */ function f1(x,y){ console.log((x+y)+"======"+this); return "這是函數的返回值"; } //apply和call調用 var r1 = f1.apply(null,[1,2]);//此時f1中的this是window console.log(r1); var r2 = f1.call(null,1,2); console.log(r2); console.log("============="); //改變this的指向 var obj = { sex:'男' }; //原本f1函數是window對象,可是傳入obj以後,f1函數此時就是obj對象的 var r1 = f1.apply(obj,[1,2]);//此時f1中的this是obj console.log(r1); var r2 = f1.call(obj,1,2);//此時f1中的this是obj console.log(r2); </script> </head> <body> </body> </html>
bind是用來複制一份的
使用的語法
函數名字.bind(對象,參數1,參數2,......)---->返回值就是賦值以後的這個函數
方法名字.bind(對象,參數1,參數2,......)---->返回值就是賦值以後的這個方法數組
function f1(x,y){ console.log(x+y+"========"+this.age); } //複製一份的時候,把參數傳入f1函數中,null默認就是this,默認就是window // var ff= f1.bind(null,10,20); // ff(); // var ff= f1.bind(null); // ff(10,20); function Person(age){ this.age=age } var per = new Person(1800); var ff = f1.bind(per,100,200); ff();
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script> function f1(fn){ console.log("f1的函數"); fn();//此時fn當成一個函數來使用的 }; //傳入匿命函數 f1(function(){ console.log("我是匿命函數"); }) //命名函數 function f2(){ console.log("f2的函數"); } f1(f2); //函數做爲參數的時候,若是是命名函數,那麼傳入命名函數的名字,沒有括號 function f3(fn){ setInterval(function(){ console.log("定時器開始"); fn(); console.log("定時器結束"); },1000) } f3(function(){ console.log("中間"); }) </script> </head> <body> </body> </html>
var arr = [99,10,100,30,50,60,20,1] //排序--函數做爲參數使用,匿命函數做爲sort方法的參數使用, //那麼此時的匿命函數中有兩個參數 arr.sort(function(obj1,obj2){ if(obj1>obj2){ return 1; } else if(obj1==obj2){ return 0; }else{ return -1; } }) console.log(arr); //字符串排序 var arr2 = ["aa-2","aa-1","ab-2","af-1","ac-1"] arr2.sort(function(a,b){ if(a>b){ return 1; }else if(a==b){ return 0 }else{ return -1 } }) console.log(arr2);
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script> //排序,每一個文件都有名字、大小、時間,能夠按照某個屬性的值進行排序 //三部電影,電影有名字,大小,上映時間 function File(name,size,time){ this.name = name; this.size = size; this.time = time; } var f1 = new File("haha.avi","500M","1997-12-10"); var f2 = new File("jjj.avi","200M","2017-12-10"); var f3 = new File("zzz.avi","100M","2007-12-10"); var arr = [f1,f2,f3]; //定義一個函數,定義傳入要排序的屬性 function fn(attr){ //函數做爲返回值 return function getSort(a,b){ if(a[attr]>b[attr]){ return 1; }else if(a[attr]==b[attr]){ return 0; }else{ return -1; } } } //聲明傳入 var ff = fn("time"); //函數做爲參數 arr.sort(ff); //循環遍歷 for(var i = 0; i < arr.length; i++){ console.log(arr[i].name+"===="+arr[i].size+"====="+arr[i].time); } </script> </head> <body> </body> </html>
閉包的概念:函數a中,有一個函數b,函數b中能夠訪問函數a中定義的變量或者是數據,此時造成閉包(這句話不嚴謹)
閉包的做用:緩存數據,延長做用域鏈
閉包的優勢和缺點:緩存數據
閉包的模式:函數模式的閉包、對象模式的閉包
閉包的應用:緩存
//函數模式的閉包 function f1(){ var num = 10; //函數聲明 function f2(){ console.log(num); } //函數調用 f2() } f1(); //對象模式的閉包 function f3(){ var num =10; var obj = { age:num } console.log(obj.age); } f3();
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> ul{ list-style: none; } li{ float: left; padding-left: 20px; position: relative; } img{ height: 300px; width: 200px; } input{ position: absolute; left: 100px; } </style> </head> <body> <ul> <li><img src="images/1_small.png"><br/><input type="button" value="贊(1)"></li> <li><img src="images/2_small.png"><br/><input type="button" value="贊(1)"></li> <li><img src="images/3_small.png"><br/><input type="button" value="贊(1)"></li> <li><img src="images/4_small.png"><br/><input type="button" value="贊(1)"></li> </ul> <script> //獲取元素 function my$(tagName){ return document.getElementsByTagName(tagName); } //閉包緩存數據 function getNumber(){ var value = 2; return function(){ this.value = "贊("+(value++)+")" } } var inputs = my$("input"); //記得要寫在頁面加載後或者文檔後 for(var i = 0 ;i < inputs.length; i++){ inputs[i].onclick=getNumber(); } </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script> (function(){ var str = "沙箱是啥呢"; console.log(str); })(); </script> </head> <body> <div>sthis is sanbox</div> <div>sthis is sanbox</div> <div>sthis is sanbox</div> <script> var getTag = 100; var objDiv = 200; //放到()()沙箱中就不會影響到 (function(){ function getTag(tagName){ return document.getElementsByTagName(tagName); } var objDiv = getTag("div"); for(var i = 0; i < objDiv.length; i++){ objDiv[i].style.border = "2px solid pink"; } })(); </script> </body> </html>
函數中調用函數本身,此時就是遞歸,遞歸必定要有結束條件
遞歸簡單解釋閉包
var i = 0; function f1(){ //若是小於5就給執行 i++; if(i<5){ f1() } console.log("從前有座山,山裏有座廟,廟裏有個和尚"); } f1();
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script> //求n個數字的和,計算機1+2+3+4+5 var sum = 0; for(var i = 0; i <= 5; i++){ sum+=i; } console.log(sum); //傳入x function getSum(x){ //x=1時返回1 if(x==1){ return 1; } //遞歸時 x傳入加上返回的x-1數一直到結束條件 return x+getSum(x-1); } console.log(getSum(5)) /* 執行過程: 執行getSum(5)---->進入函數,此時x是5,執行的是5+getSum(4),此時代碼等待 此時5+getSum(4),代碼先不進行計算,先執行getSum(4),進入函數, 執行的是4+getSum(3)...一直到getSum(1),執行到x==1 return 1, 此時getSum(1)的結果是1,開始向外走出去 2+getSum(1)此時的結果是:2+1 ... ... ... 結果:15 */ </script> </head> <body> </body> </html>
執行過程圖
app
//遞歸案例:求一個數字各個位數上數字的和 123=====1+2+3 function getEverySum(x){ if(x<10){ return x; } //獲取的是這個數字的個位數 return x%10+getEverySum(parseInt(x/10)); } console.log(getEverySum(1234));