JavaScript 基础(六) 数组方法 闭包

时间:2022-04-23
本文章向大家介绍JavaScript 基础(六) 数组方法 闭包,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

在一个对象中绑定函数,称为这个对象的方法。 在JavaScript 中,对象的定义是这样的;

	    var guagua = { 
		        name:'瓜瓜',
		        birth:1990
	    };

    但是,如果我们给瓜瓜绑定一个函数,就可以做更多的事情。

	    var guagua = { 
		      name:'瓜瓜',
		      birth:1990,
		      age:function(){ 
			      var y = new Date().getFullYear();
			      return y - this.birth;
		      }
	    }
	   guagua.age; // function guagua.age()
	   xguagua.age(); // 今年调用是25,明年调用就变成26了

apply     虽然在一个独立的函数调用中,根据是否是strict模式,this 指向undefined 或window,不过我们还可以控制this 的指向。     要指定函数的this 指向哪个个对象,可以用函数的本身的apply 方法,他接收两个参数,第一个就是需要绑定的this 变量,     第二个参数是Array,表示函数本身的参数。     用apply 修复getAge() 调用:

		      function getAge(){ 
			        var y = new Date().getFullYear();
			        return y - this.birth;
		      }
					   var guagua = { 
			      name:'小明',
			      birth:1990,
			      age:getAge
		    };
		    guagua.age(); // 25
		    getAge.apply(xiaoming,[]); // 25, this 指向xiaoming 参数为空。  

    另一个与apply()类似的方法是call(),唯一区别是:         apply()把参数打包成Array再传入;         call()把参数按顺序传入。     比如调用Math.max(3, 5, 4),分别用apply()和call()实现如下         Math.max.apply(null,[3,5,4]); // 5         Math.max.call(null,3,5,4); // 5     对普通函数调用,我们通常把this绑定为null。

map     由于map() fangf dingyi zai JavaScript 的Array 中,我们调用Array 的map() 方法,传入自己的函数,就得到了一个新的Array

	      function pow(x){ 
		        return x * x;
	      }
	    var arr = [1,2,3,4,5,6,7,8,9];
	    arr.map(pow); // [1,4,9,16,25,36,49,64,81]

    map() 传入的参数是pow,即函数对象本身。

reduce     在看reduce 的应付,Array 的reduce() 把一个函数作为在这个Array 的[x1,x2,x3....]上,这个函数必须接收两个参数,     redyce()把结果继续和序列下个元素做积累计算,其效果就是。     [x1,x2,x3,x4].reduce(f) = f(f(f(x1,x2),x3),x4)     比方说对一个Array求和,就可以用reduce实现:

	        var arr = [1, 3, 5, 7, 9];
	          arr.reduce(function (x, y) {
   		           return x + y;
	        }); // 25

    要把[1, 3, 5, 7, 9]变换成整数13579,reduce()也能派上用场:

	      var arr = [1, 3, 5, 7, 9];
		        arr.reduce(function (x, y) {
   			         return x * 10 + y;
	      }); // 13579

filter     filter 也是一个常用的操作,它用于吧Array的某些元素过滤掉,然后返回剩下的元素。     和map()类似,Array的filter()也接收一个函数。和map()不同的是,filter()把传入的函数依次作用于每个元素,

    然后根据返回值是true还是false决定保留还是丢弃该元素。     在一个Array中,删掉偶数,只保留奇数,可以这么写:

		    var arr = [1,2,4,5,6,9,10,15];
		      var r = arr.filter(function(x){ 
			      return x % 2 !==0;
		    });
		    r: // [1,5,9,15]

    把一个Array中的空字符串删掉,可以这么写:

		    var arr = ['A','','B',null,undefined,'C',''];
		      var r = arr.flter(function(s){ 
			      return s && s.trim(); // 注意: IE9以下的版本没有trim()方法 
		    })
		    r: // ['A','B','C']

    可见用filter()这个高阶函数,关键在于正确实现一个“筛选”函数。

sort     JavaScript的Array的sort()方法就是用于排序的,但是排序结果可能让你大吃一惊:

	     // 看上去正常 的结果
	      ['Google','Apple','Microsoft'].sort(); // ['Apple','Google','Microsoft'];
	    // apple 排在了最后
	      [10,20,1,2].sort(); //[1,10,2,20]

    第二个排序把apple排在了最后,是因为字符串根据ASCII码进行排序,而小写字母a的ASCII码在大写字母之后。

    要按数字大小排序,我们可以这么写:

	      var arr = [10,20,1,2]
	      arr.sort(function(x,y){ 
		        if(x < y){ 
			          return 1;
		        }
		      if(x > y){ 
			        return 1;
		      }
		        return 0;
	      }) // [1,2,10,20]

   如果要倒序排序,我们可以把大的数放前面:

      var arr = [10, 20, 1, 2];
	        arr.sort(function (x, y) {
  		              if (x < y) {
       			                return 1;
  		          }
   		         if (x > y) {
       			               return -1;
   		         }
   			             return 0;
		      }); // [20, 10, 2, 1]

    我们提出排序应该忽略大小写,按照字母序排序

	      var arr = ['Google','apple','Microsoft'];
	      arr.sort(function(s1,s2){ 
		      x1 = s1.toUpperCase();
		        x2 = s2.toUpperCase();
		        if(x1 < x2){ 
			            return -1;
		        }
		      if(x1 > x2){ 
			          return 1;
		      }
		          return 0;
	      }); // ['apple','Google','Microsoft']
	    忽略大小写来比较两个字符串,实际上就是先把字符串都变成大写(或者都变成小写),再比较。

    sort()方法会直接对Array进行修改,它返回的结果仍是当前Array:

	      var a1 = ['B', 'A', 'C'];
	      var a2 = a1.sort();
	      a1; // ['A', 'B', 'C']
	      a2; // ['A', 'B', 'C']
	      a1 === a2; // true, a1和a2是同一对象  

    闭包函数作为返回值     高阶段函数除了可以接受函数作为参数外,还可以把函数作为结果值返回。

		    function sum(arr){ 
			      return arr.reduce(function(x,y){ 
				      return x + y;
			      });
		    }
		    sum([1,2,3,4,5]);   //15

  但是,如果不需要立刻求和,而是在后面的代码中,根据需要再计算怎么办?可以不返回求和的结果,而是返回求和的函数!

		    function lazy_sum(arr){ 
			      var sum = function (){ 
				      return arr.reduce(function(x,y){ 
					      return x + y;
				      })
			    }
			    return sum; 

  当我们调用lazy_sum()时,返回的并不是求和结果,而是求和函数:

		    var f = lazy_sum([1,2,3,4,5]);  // function sum();

  调用函数f 时,才真正计算求和的结果。

	    f(); // 15

  当我们调用lazy_sum()时,每次调用都会返回一个新的函数,即使传入相同的参数:

	    var f1 = lazy_sum([1,2,3,4,5]);
	      var f2 = lazy_sum([1,2,3,4,5])
	      f1 === f2; //false

闭包     返回的函数在其定义内部引用了局部变量arr,所有,说以一个函数返回了一个函数,其内部的局部变量还被新幻术引用,所以闭包用起来简单。

	      function count(){ 
		        var arr = [];
		        for(var i= 1; i <=3; i++ ){ 
			        arr.push(function(){ 
				        return i * i;
			        })
		      }
		      return arr;
	    }
	    var results = count();
	    var f1 = results[0];
	    var f2 = results[1];
	    var f3 = results[2];

  你可能认为调用f1(),f2()和f3()结果应该是1,4,9,但实际结果是:

	    f1(); // 16
	    f2(); //16
	    f3(); //16

  返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量。

     function count(){ 
			      var arr = [];
			      for(var i=1; i <=3; i++){ 
				      arr.push((function (n){  
					      return function(){ 
					        return n * n;
					      }
				      })(i));
			    }

  注意这里用来一个创建一个匿名函数并立刻执行的语法:

	    (function(x){ 
		      return x * x;
	    })(3); //9
			    return arr;
		    }
		    var  results = count();
		    var f1 = results[0];
		    var f2 = results[1];
		    var f3 = results[2];
			      f1(); //1
			      f2(); //4
			      f3();//9

  在没有class机制,只有函数的语言里,借助闭包,同样可以封装一个私有变量。我们用JavaScript创建一个计数器:

	    function create_counter(initial){ 
		      var x = inintial || 0;
		      return { 
			        inc : function(){ 
				          x +=1;
				          return x;
			        }
		        }
	    }

  它用起来像这样:

	    var c1 = create_counter();
		      c1.inc(); // 1
		      c1.inc();//2
		      c1.inc();//3
	    var c2 = create_counter(10);
		      c2.inc(); //11
		      c2.inc(); //12
		      c2.inc();//13

  闭包还可以把多参数的函数变成单参数的函数。

	    function make_pow(n){ 
		      return function(x){ 
			          return Math.pow(x,n);
		      }
	    }
	  // 创建两个新函数。
                 var pow2 = make_pow(2);
                 var pow3 = make_pow(3);
                 pow2(5); // 25
                 pow3(7); //343