第10天:apply和call、bind、函數做爲參數、返回值使用、閉包、遞歸的樣例

apply和call

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是用來複制一份的
使用的語法
函數名字.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

//遞歸案例:求一個數字各個位數上數字的和  123=====1+2+3
    function getEverySum(x){
        if(x<10){
            return x;
        }
        //獲取的是這個數字的個位數
        return x%10+getEverySum(parseInt(x/10));
    }
    console.log(getEverySum(1234));
相關文章
相關標籤/搜索