• JS call、apply、bind、递归、闭包


    call、apply、bind方法用来处理函数内部的this指向问题

    在(https://www.cnblogs.com/qimuz/p/12740831.html)中介绍了用构造函数来创建对象,其中里面的this指的是谁调用this,它就指向谁。

    function animal() {}
    animal.prototype = {
        color: "grey",
        look: function() {
            console.log("It's color is " + this.color);
        }
    };
    var dog = new animal();
    dog.look(); // It's color is grey
    var cat = new animal();
    cat.look(); // It's color is grey
    

    上图所示,打印出来的都是“It's color is grey”,但是如果我们想改变cat的颜色,就要重新定义一个look方法,如果改变的多了,就会很麻烦。

    call()

    call() 方法调用一个函数, 它具有一个指定的 this 值和分别地提供的参数

    fun.call(thisArg, arg1, arg2, ...)
    
    • thisArg指的是在 fun 函数中指定的 this的值,是一个可选项

    • arg1, arg2, …指定的参数列表,也是可选项

    • 使用调用者提供的 this 值和参数调用该函数的返回值。若该方法没有返回值,则返回 undefined。

    • call()允许为不同的对象分配和调用属于一个对象的函数/方法

    • call()提供新的 this 值给当前调用的函数/方法。可以使用 call() 来实现继承:写一个方法,然后让另外一个新的对象来继承它,而不是在新对象中再写一次这个方法

      比如前面的例子可以改为:

      //使用 call() 方法调用函数并且指定上下文的 this
      function animal() {}
      animal.prototype = {
      color: "grey",
      look: function() {
      console.log("It's color is " + this.color);
      	}
      };
      
      var dog = new animal();
      cat = {
      color:"white"
      };
      dog.look.call(cat); 
      

      这样就更改了cat的颜色,输出为"It's color is white"

      除此之外,还可以通过调用父构造函数的call()方法来实现继承

      apply()

      这个方法与call方法类似,区别就是call方法里面接受的是参数,而apply方法接受的是数组

      fun.apply(thisArg, [argsArray]);
      

      1、将数组添加到另一个数组

      var arr = ["a", "b", "c"];
      var nums = [1, 2, 3];
      arr.push.apply(arr, nums);
      console.log(arr);  //返回["a", "b", "c", 1, 2, 3]
      

      结果为["a", "b", "c", 1, 2, 3]

      concat()、push()、apply()的区别:

      concat() 方法连接数组,不会改变原数组,而是创建一个新数组

      push() 是接受可变数量的参数的方式来添加元素

      apply() 则可以连接两个数组

      2、apply() 方法及内置函数

      var numbers = [3, 4, 6, 1, 9];
      var max = Math.max.apply(null, numbers);
      console.log(max);  //返回9
      

      bind()

      bind()方法创建一个新的函数(称为绑定函数),在调用时设置 this 关键字为提供的值。并在调用新函数时,将给定参数列表作为原函数的参数序列的前若干项。

      fun.bind(thisArg[, arg1[, arg2[, ...]]])
      

      thisArg指的是当绑定函数被调用时,该参数会作为原函数运行时的 this 指向。当使用 new 操作符调用绑定函数时,该参数无效。参数:arg1,arg2,…表示当目标函数被调用时,预先添加到绑定函数的参数列表中的参数。

      this.num = 6;
      var test = {
        num: 66,
        getNum: function() {
          return this.num;
        }
      };
      test.getNum(); // 返回 66
      var newTest = test.getNum;
      newTest(); // 返回 6
      // 创建一个新函数,将"this"绑定到 test 对象
      var bindgetNum = newTest.bind(test);
      bindgetNum(); // 返回 66
      

      递归

      在一个函数里,自己调用自己,就称为递归调用

      function fun(){
      			fun();
      			console.log('Hello World');
      			}//一定要写临界条件,不然程序无法结束并且会报错
      			fun();
      

      1、函数+变量

      例:求 1 到 100之间的整数相加的和

      function sum(n){
      		if(n==0){
      			return 0;
      		}else{
      			return n+sum(n-1);
      			}
      		}
      		var i = sum(100);
      		console.log(i);
      

      例:求10的阶乘

      function fun(n){
      		if(n==1){
      			return 1;
      		}else{
      			return n*fun(n-1);
      			}
      		}
      		var i = fun(10);
      		console.log(i);
      

      2、函数+函数

    斐波拉契题
    --从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,每个月的兔子对数为多少?

    产量分析:1, 1, 2, 3, 5, 8, 13, 21 .......

    第n个月的兔子总数 = 第n-1个月的兔子总数 + 第n-2个月的兔子总数

    问题: 求任意月兔子的总数

    function func( n )
    {
        if (n == 0 || n == 1){
            return 1;
        }else{
            return func(n-1) + func(n-2);
        }
    }
    
    var i = func(11);
    console.log(i);
    

    闭包

    指的是函数可以使用函数定义之外的变量,每当函数被创建,就会在函数生成时生成闭包

    先来了解一下作用域这个概念:

    作用域

    作用域的值就是作用范围,也就是说一个变量或函数在什么地方可以使用,在什么地方不能使用

    函数作用域

    ​ 指的是在函数内部声明的变量在这个函数体内是可见的

    function test() {
      var num = 123;
      console.log(num); //123
      if (2 == 3) {
        var k = 5;
        for (var i = 0; i < 10; i++) {}
        console.log(i);
      }
      console.log(k); // 不会报错,显示 undefined
    }
    test();
    

    全局作用域

    指的就是在什么地方都能够访问到它

    • 内层作用域可以访问外层作用域,反之不行。
    • 整个代码结构中只有函数可以限定作用域。
    • 如果当前作用规则中有名字了,就不考虑外面的同名变量。
    • 作用域规则首先使用提升规则分析。

    再来看闭包~

    简单的闭包:全局变量

    复杂的闭包:

    function f1() {
    		 var num=10;
    		function f2() {
    		console.log(num);
    			}
    		 //函数调用
    		 f2();
    			}
    		f1(); //10
    

    闭包可用来缓存数据~

  • 相关阅读:
    [转]:Android 5.0的调度作业JobScheduler
    Android 移动端数据结构
    算法-二分查找
    设计模式-设计原则
    设计模式-单例模式(Singleton Pattren)(饿汉模式和懒汉模式)
    Android 7.0 Dialog 无法显示的问题
    设计模式-装饰模式(Decorator Pattern)
    产品中心2
    java中static和final修饰符
    java访问修饰符
  • 原文地址:https://www.cnblogs.com/qimuz/p/12757665.html
Copyright © 2020-2023  润新知