07 (H5*) js课程第8天 高阶函数、闭包、沙箱

目录:

1:call和apply方法调用

2:bind方法复制

3:函数中的几个属性值 

4:高阶函数,函数作为参数

5:高阶函数,函数作为返回值。

6:   作用域链,作用域,预解析

7:闭包--延长作用域链

8:  沙箱:测试,虚拟环境

 

1:call和apply方法调用

<script>
        function f1 (x, y) {
            console.log("结果是:"+(x+ y) + this);
        }
        
        // 函数的调用
        f1(10, 20);

        console.log("===========");

        //1:  此时的f1实际上是当成对象来使用的,对象可以调用方法,apply和call方法也是函数的调用的方式
        
        f1.apply();
        f1.call();


        //2:  apply和call都可以让函数或者方法来调用,传入参数和函数自己调用的写法不一样,但是效果是一样的, apply传入的是数组,  call,传入的是参数
    
        f1.apply(null, [100, 200]);

        f1.call(null, 100, 200);
        console.log("===========");

        function f2(x, y){
            console.log("这个函数是window对象的一个方法"+ (x+y) + this);
            console.dir(this);
        }

        window.f2(10, 20);

        var obj = {
            age: 10,
            name: "张三",
        }

        //3:  apply和call可以改变this的指向,
        window.f2.call(obj, 10, 20);
        window.f2.apply(obj, [10,20]);


        // 4:apply和call方法实际上并不在函数这个实例对象中,而是在Function的prototype,原型对象中。
        原型对象可以看成+方法,实例方法可以当成-方法。调用+方法时候可以当成对象。
console.log(f2.__proto__ == Function.prototype); console.log(Function.prototype); //{ [native code] } console.dir(Function); script>

 

  

2:bind方法复制 

<script>
        
        console.log("=====  11 =====")
        function f1 (x, y ){
            console.log((x+y) + " :======>>>>"+this );
            console.dir(this);
        }    
        
        f1.bind();

        //  方法复制了一份,并且传递参数,结果还是方法,方法没有调用。此时f1是对象。
        //   bind方法是复制的意思,可以在复制的时候传递参数,也可以在复制之后传递参数
        //  apply 和 call 是调用的时候改变this的指向
        //  bind是 复制的时候修改this的指向
        var ff = f1.bind(null, 10, 20);

        console.log (ff);

        ff();


        var f2 = f1.bind(null);
        f2(10, 20);
        console.log("=====  22 =====")


        // bind是方法复制,apply和call是方法调用
        function Person (){
            this.age = 10;
        }

        Person.prototype.eat = function () { 
            console.log("这个是吃");
         };

         var per = new Person;

         var ff = f1.bind(per);

         ff(10, 20);


         console.log("=====  33 =====")

         function Person(age) {
             this.age = age;
         }

         Person.prototype.play = function () {
             console.log(this + "========>>>>" + this.age);
         }


         function Student (age) {
             this.age = age;
         }

         var per = new Person(10);
         var stu = new Student(20);

         var paly2 = per.play.bind(stu);

         paly2();

    script>

 

3:  函数中几个属性

<script>
        //函数中有一个name属性----->函数的名字,name属性是只读的,不能修改
        //函数中有一个arguments属性--->实参的个数
        //函数中有一个length属性---->函数定义的时候形参的个数
        //函数中有一个caller属性---->调用(f1函数在f2函数中调用的,所以,此时调用者就是f2)
        function f1(x,y) {
          console.log(f1.name);
          console.log(f1.arguments.length);
          console.log(f1.length);
          console.log(f1.caller);//调用者
        }
       f1.name="f5";
       f1(10,20,30,40);
       console.dir(f1);
    
    
        function f2() {
          console.log("f2函数的代码");
          f1(1,2);
        }
        f2();
    script>

 

4:高阶函数之参数是函数

<script>
    
     //fn是参数,最后作为函数使用了,函数是可以作为参数使用
    function f1(fn) {
        console.log("f1的函数");
        fn();//此时fn当成是一个函数来使用的
    }
   

    //1:  传入匿名函数
    f1(function () {
        console.log("我是匿名函数");
    });

    console.log("=======  22  ========");
    // 命名函数
    function f2() {
         console.log("f2的函数");
    }

    // 2:传入的是命名函数
    f1(f2);
    //函数作为参数的时候,如果是命名函数,那么只传入命名函数的名字,没有括号
    
    script>

 

 

5: 函数作为返回值

 <script>
        
        console.log("========  11  =========");
        function f1() {
            console.log("f1函数的开始");

            return function () { 
                console.log("我是函数,但是我是我是我为函数的返回值");
            };

             //  我是不会执行的,因为此行代码上面有return
            console.log("f1函数的结束");
        }  
        
        var f2 = f1();
        f2();


        console.log("========  22  =========");
        var num=10;
        console.log(typeof num);//获取num这个变量的数据类型
        var obj={};//对象
        //判断这个对象是不是某个类型的
        console.log(obj instanceof Object);
        //获取某个对象的数据类型的样子
        //Object.prototype.toString.call(对象);//此时得到的就是这个对象的类型的样子
        
        
        
        //此时输出的是Object的数据类型   [object Object]
        console.log(Object.prototype.toString());
        //输出的数组的数据类型      [object Array]
        console.log(Object.prototype.toString.call([]));
        
        var arr=[10,20,30];
        console.log(Object.prototype.toString.call(arr));
        
        console.log("========  33  =========");

        //获取某个对象的类型是不是你传入的类型
        //[10,20,30] 是不是"[object Array]"
        //type---是变量----是参数----"[object Array]"
        //obj---是变量-----是参数----[10,20,30];

        //判断这个对象和传入的类型是不是同一个类型
        function getFunc(type) {
            return function (obj) {
                return Object.prototype.toString.call(obj) === type;
            }
        }

        var ff = getFunc("[object Array]");
        var result = ff([10, 20, 30]);
        console.log(result);

        var ff1 = getFunc("[object Object]");
        var dt = new Date();
        var result1 = ff1(dt);
        console.log(result1);
    script>

 

6:作用域,作用域链,预解析

1:局部变量。函数中的变量是局部变量,外边无法访问。

2:预解析:变量的声明,和函数的声明提前

<script>

            // 变量---->局部变量和全局变量,
            // 作用域:就是变量的使用范围
            // 局部作用域和全局作用域
            // js中没有块级作用域---一对括号中定义的变量,这个变量可以在大括号外面使用
            // 函数中定义的变量是局部变量
            
               while(true){
                 var num=10;
                 break;
               }
               console.log(num);
            
               {
                 var num2=100;
               }
               console.log(num2);
            
               if(true){
                 var num3=1000;
               }
               console.log(num3);
            
               function f1() {
                 //局部变量
                 var num1=10;
               }
            //    console.log(num1);
            
               console.log("========  22  ======");
                // 作用域链:变量的使用,从里向外,层层的搜索,搜索到了就可以直接使用了
                // 层层搜索,搜索到0级作用域的时候,如果还是没有找到这个变量,结果就是报错
               var num=10; //作用域链 级别:0
               var num2=20;
               var str = "abc"
               function f1() {
                 var num2=20;
                 function f2() {
                   var num3=30;
                   console.log(num);
                 }
                 f2();
               }
               f1();
            
            
                //预解析:就是在浏览器解析代码之前,把变量的声明和函数的声明提前(提升)到该作用域的最上面
            
                //变量的提升
                console.log(num);
                var num=100;
            
                //函数的声明被提前了
                f1();
                function f1() {
                  console.log("这个函数,执行了");
                }
            
                var f2;
                f2=function () {
                  console.log("小杨好帅哦");
                };
                f2();
              script>

 

 7:闭包

1:闭包的定义:

函数A中,有一个函数B,函数B中可以访问函数A中定义的变量或者数据,此时就行程了闭包。
 闭包缓存数据
 总结:如果想要缓存数据,需要把数据放在外层函数和内层函数之间。
 
 闭包的作用:缓存数据。优点也是缺点,没有及时释放
 局部变量在函数中,函数使用结束后,局部变量就会被自动释放。
 闭包后,里面的局部变量的使用作用域链就会被延长。

 

<script>
        /* 闭包
         * 闭包的概念:函数A中,有一个函数B,函数B中可以访问函数A中定义的变量或者数据,此时就行程了闭包。

         *闭包的模式:函数闭包和对象闭包

         * 闭包的作用:缓存数据,延长作用域链

         * 闭包的优点和缺点:缓存数据

         * 闭包的应用:

         * ****/


         console.log("=======  11  ========");
        //  1:函数式闭包
         function f1() {
             var num = 10;

             // 函数
             function f2() {
                 console.log(num);
             }

             f2();
         }

         f1();

         console.log("=======  22  ========");
        //  2:对象是闭包
        function  f3() {

            var num1 = 20;

            // 对象
            var obj = {
                age : num1,
            }

            console.log(obj.age);
        }

        f3();

        console.log("=======  33  ========");

        function f4() {
            var num4 = 40;
            return function () { 
                console.log(num4); 
                return num4;
            };
        }
 
        var ff1 = f4();
        var result =  ff1();
        console.log(result);
        

        console.log("=======  44  ========");
        function f5() {
            var num5 = 50;
            var obj = {
                age : num5,
            }
            return obj;
        }

        var resultObj = f5();
        var result5 = resultObj.age;
        console.log(result5);
    script>

 

2:闭包的例子

<script>
    
    console.log("=======  11  =========");
    function f1 () { 
        var num = 10;
        num ++ ;
        console.log(num);
    }
    
    f1(); // 11
    f1(); // 11
    f1(); // 11

    console.log("=======  22  =========");

    // 闭包缓存数据
    // 总结:如果想要缓存数据,需要把数据放在外层函数和内层函数之间。
    // 闭包的作用:缓存数据。优点也是缺点,没有及时释放
    //  局部变量在函数中,函数使用结束后,局部变量就会被自动释放。
    //  闭包后,里面的局部变量的使用作用域链就会被延长。
    function f2() {
        var num = 20;
        return function () { 
            num ++;
            return num;
        };
    }

    var ff1 = f2();
    console.log(ff1());  // 21
    console.log(ff1());  // 22
    console.log(ff1());  // 23  

    console.log("=======  33  =========");

    // 产生3次相同的随机数
    // 
    function f3() {
        var num3 = parseInt(Math.random()*10+1);
        return function () {  
            console.log(num3);
        }
    }

    var ff3 = f3();
    ff3();
    ff3();
    ff3();


    script>

 

 8:沙箱:虚拟测试和真实世界结果一样,不影响真实世界。

 

1:沙箱的定义和2中格式

<script>
       //沙箱:环境,黑盒,在一个虚拟的环境中模拟真实世界,做实验,实验结果和真实世界的结果是一样,但是不会影响真实世界 
        
       // 沙箱 函数的自调用

       console.log("========  11  ========");
       // 沙箱的模板,函数自调用两种格式
        //   格式一:       ()();
       (function () {  
        var num = 10;
        console.log(num + 10);
       })();



       // 格式二:使用的比较多.    (());
       (function () {  
        var num = 10;
        console.log(num + 20);
       }());

     
    script>

 

9:递归

1:定义:自己调用自己一定  要有结束条件。

<script>
        
        console.log("=======  11  =======");
        // 求n个数的和
        // 倒序递归,结束条件 5+4+3+2+1
        function getSum(n) {
            // 结束条件
            if(n ==1){
                return 1;
            }
 
            return n + getSum(n - 1);
        }
       
        console.log(getSum (5));

        /*
        *
        * 执行过程:
        * 代码执行getSum(5)--->进入函数,此时的x是5,执行的是5+getSum(4),此时代码等待
        * 此时5+getSum(4),代码先不进行计算,先执行getSum(4),进入函数,执行的是4+getSum(3),等待, 先执行的是getSum(3),进入函数,执行3+getSum(2),等待,先执行getSum(2),进入函数,执行 2+getSum(1);等待, 先执行getSum(1),执行的是x==1的判断,return 1,所以,
        * 此时getSum(1)的结果是1,开始向外走出去
        * 2+getSum(1) 此时的结果是:2+1
        * 执行:
        * getSum(2)---->2+1
        * 3+getSum(2) 此时的结果是3+2+1
        * 4+getSum(3) 此时的结果是4+3+2+1
        * 5+getSum(4) 此时的结果是5+4+3+2+1
        *
        * 结果:15
        *
        * */


        
    script>

 

 

注意:

你可能感兴趣的:(07 (H5*) js课程第8天 高阶函数、闭包、沙箱)