zoukankan      html  css  js  c++  java
  • 高级js--(面向对象js,arguments,闭包,自调)

    1. Arguments对象
       l检测参数个数
    1.在函数代码中,使用特殊对象 arguments,开发者无需明确指出参数名,就能访问它们。

              function howManyArgs() {

          alert(arguments.length);

    }

    howManyArgs("string", 45);//输出 2

    howManyArgs();//输出 0

    howManyArgs(12);//输出 1

    • 模拟函数重载

         function doAdd() {

      if(arguments.length == 1) {

      alert(arguments[0] + 5);

      } else if(arguments.length == 2) {

      alert(arguments[0] + arguments[1]);

      }

    }

      doAdd(10); //输出 "15"

      doAdd(40, 20); //输出 "60"

    2.变量的作用域
      l全局变量与局部变量(为什么)

    var global = 1;

    function f(){

      var local = 2;

      global++;

      return "global = "+global;

    }

    alert(f());  //output  global = 2

    alert(f());  //output  global = 3

    alert(local);  //output  local is undefined

    结论:全局变量的值会被局部变量修改。而函数外部无法访问局部变量。

     l声明局部变量(没有使用var

    function f(){

      local = 2;

    }

    alert(local);  //output  local is undefined

    f(); 

    alert(local);  //output  global = 2

    说明:

    l在函数f() 中定义了一个变量local。在该函数被调用之前,这个变量是不存在的。

     

    llocal变量会在f() 函数首次被调用时创建,并赋予全局作用域。
    函数域与全局域

    var a = 123;

    function f(){

      alert(a);  //output  undefined

      var a = 1;

      alert(a);  //output  1

    }

    f();

    结论

    l函数域始终优先于全局域,所以局部变量a会覆盖与它同名的全局变量。

    3.匿名函数

    javascript可以将函数作为数据使用。作为函数本体,它像普通的数据一样,不一定要有名字。默认名字的函数被称之为“匿名函数”。例如:

    function (a){return a;}

    匿名函数的两种用法:

    l可以将匿名函数作为参数传递给其他函数。这样,接收方函数就能利用所传递的函数来完成某些事情。
    l可以定义某匿名函数来执行某些一次性任务

    4.回调函数

    function add(a, b){

      return a() + b();

    }

    var one = function(){return 1;}

    var two = function(){return 2;}

    alert(add(one,two));  //output  3

     

    //可以直接使用匿名函数来替代one()two(),以作为目标函数的参数(这才是回调函数,上面的不是

    alert(add(function(){return 1;}, function(){return 2;}));

    总结

    l在这个例子中,函数onetwo都是回调函数。

     

    l当将函数A传递给函数B,并由B来执行A时,A就成了一个回调函数(callback function)。如果A还是一个无名函数,就称之为匿名回调函数。

    l回调函数的优点:(总结)

    l它可以在不做命名的情况下传递函数(这意味着可以节省全局变量)。
    l可以将一个函数调用操作委托给另一个函数(这意味着可以节省一些代码编写工作)。
    l回调函数也有助于提升性能。(重要)

    l下面的代码,利用回调函数如何优化?

      //该函数通过一个循环将其所接收的三个参数分别乘以2,并以数组的形式返回结果

      function two(a, b, c){

      var i, arr = [];

      for(i = 0;i < 3; i++){

      arr[i] = arguments[i] * 2;

      }

      return arr;

      }

     

      //将接收的参数加一后返回

      function addone(a){

      return a + 1;

      }

     

      //测试上面的两个函数

      alert(two(1, 2, 3));  //output  [2, 4, 6]

      alert(addone(100));  //output  101

     

      //将三个数据在两个函数之间传递

      var myarr = [];

      myarr = two(10, 20, 30);

      for(var i = 0; i < 3; i++){

      myarr[i] = addone(myarr[i]);

      }

      alert(myarr);  //output  [21, 41, 61]

       ------------------------------------------------------------------------

        /*

       * 以上代码可以工作,但是显然不够优化。

       * 这里使用了两次循环。如果处理的数据量很大火循环操作很复杂的话,开销一定不小。

       */

     

      //优化之后的代码(修改two函数)

      function two(a, b, c, callback){

      var i, arr = [];

      for(i = 0;i < 3; i++){

      arr[i] = callback(arguments[i] * 2);

      }

      return arr;

      }

     

      myarr = two(1, 2, 3, addone);

      alert(myarr);  //output  [3, 5, 7]

     

      //还可以使用匿名函数来替代addone函数

      myarr = two(1, 2, 3, function addone(a){return a + 1;});

    5.自调函数

     

    自调函数 —— 其实就是在定义函数后自行调用。(思考:自调函数的优点)
    (1)例如:


     (
      function(){
      alert("javascript");
      }
     )()
    解释说明:
    l第一对括号,放置的是一个匿名函数。
    l第二对括号的作用,是“立即调用”。
    l自调函数只需:将匿名函数的定义放进一对括号中,然后外面再跟一对括号即可。

    (2)例如:

    (

      function(name){

      alert("Hello " + name + "!");

      }

     )("javascript")

      //output  Hello javascript!

    解释说明:

    l第一个括号中的匿名函数接受一个参数。
    l第二个括号,在调用时,向匿名函数传递参数内容。
    6.内部(私有)函数

      function a(param){

      function b(input){

      return input * 2;

      };

      return "The result is " + b(param);

      }

     

      alert(a(2));  //The result is 4

        解释说明:
    l当调用全局函数a ( ) 时,本地函数b ( ) 也会在其内部被调用。由于b ( ) 是本地函数,它在a ( ) 以外的地方是不可见的,所以将b 称之为私有函数。

    总结:
     l私有函数的优点:

    l有助于确保全局名字空间的纯净性(这意味着命名冲突的机会很小)。
    l私有性 —— 只将一些必要的函数暴露给“外面世界”,并保留属于自己的函数,使它们不为该应用程序的其他部分所用。
    7.闭包
        7.1作用域链
    ljavascript不存在大括号级的作用域,但具有函数作用域。
    l在函数内定义的变量在函数外是不可见的。但如果该变量是在某个代码块中定义的(如在某个iffor语句中),它在代码块外是可见的。(不太明白这是什么意思?)
    例如1:

      var a = 1;

      function f(){

      var b = 2;

      return a;

      }

     

      alert(f());  //output  1

      alert(b);  //output  b is undefined

    补充说明:

    l变量a 是属于全局域的,变量b 的作用域是属于函数f ( ) 
    lf ( ) 内,a b 都是可见的
    lf ( ) 外,a 是可见的,b 则是不可见的。
    例如2:

      var a = 1;

      function f(){

      var b = 2;

      function n(){

      var c = 3;

      alert(a);  //output  1

      alert(b);  //output  2

      alert(c);  //output  3

      }

      return n();

      }

      f();

        补充说明:    

     

    l函数n ( ) 可以访问的变量可以是自身的作用域,也可以是其“父级”的作用域。这就形成了一条作用域链。

        例如3:

      function f1(){

      var a = 1;

      f2();

      }

      function f2(){

      return a;

      }

     

      alert(f1());  //output  a is undefined

    补充说明:

    l在定义函数f1 ( ) f2 ( ) 时,只能访问全局作用域和其自身的作用域
    l在定义函数f2 ( ) 时,变量a 是不可见的。
    例如4:

    var a = 5;

      function f1(){

      var a = 1;

      f2();

      }

      function f2(){

      return a;

      }

     

      alert(f1());  //output  5

    补充说明:

    l在定义函数f1 ( ) f2 ( ) 时,都是可以访问全局作用域的。
        7.1闭包 
     
    l定义指的是词法表示包括不被计算的变量的函数,也就是说函数可以使用函数之外定义的变量(本质)
    l闭包的实现

    var b;

      function a(){

      var a = "a";

      b = function(){

      return a + "b";

      }

      return a;

      }

     

      //测试

      alert(a());  //output  a

      alert(b());  //output  ab

    补充说明:
    la ( ) 函数中定义了 b ( ) 函数,所以b ( ) 函数可以访问a ( ) 函数的作用域
    l b ( ) 函数升级到全局函数,但依然保留可以对a ( ) 函数作用域的访问权。
     
        7.1循环中的闭包 
            例如1:(小难) 

      function f(){

      var a = [];

      var i;

      for(i = 0; i < 3; i++){

      a[i] = function(){//a[i]是一个闭包

      return i;

    }

      }

      return a;

      }

     

      var fun = f();

     

      alert(fun[0]());  //output  3

      alert(fun[1]());  //output  3

      alert(fun[2]());  //output  3

    补充说明:

    l按照预期,最终结果应该输出 [0 , 1 , 2 ],但是却是[ 3 , 3 , 3 ]
    l在函数 f ( ) 中,我们通过循环,创建了三个闭包,它们都指向了共同的局部变量 i 
    l但是闭包并不会记录它们的值,它们所拥有的只是一个 i 的连接(即引用),因此只能返回i 的当前值。
    例如2:(对比例1)

    function f(){

      var a = [];

      var i;

      for(i = 0; i < 3; i++){

      a[i] = (function(x){

      return x;

      })(i);

      }

      return a;

    }

     

    var fun = f();

     

    alert(fun[0]);  //output  0

    alert(fun[1]);  //output  1

    alert(fun[2]);  //output  2

    补充说明:

    l在这里,我们不再直接创建一个返回i 的函数,而是将i 传递给了一个自调函数。
    l在该自调函数中,i 就被赋值给了局部变量x ,这样一来,每次迭代中的x 就会拥有各自不同的值了
    例如3:下面这种,是不使用自调函数的用法。

    function f(){

      function n(x){

      return x;

    }

      var a = [];

      var i;

      for(i = 0; i < 3; i++){

      a[i] = n(i);

      }

      return a;

    }

     

      var fun = f();

     

      alert(fun[0]);  //output  0

      alert(fun[1]);  //output  1

      alert(fun[2]);  //output  2

     
     
  • 相关阅读:
    C++中如何使用大整数__int 128
    全排列问题
    读书札记:瑞士法郎的因素
    读书札记:影响欧元的因素
    金融市场:最全的外汇平台资料大全(包括开户金额、点差、特色!)
    读书札记:澳大利亚元因素
    情感日记:祭衣文
    情感日记:第一次亲密的接触
    读书札记:美元影响的因素
    读书札记:外汇市场
  • 原文地址:https://www.cnblogs.com/zhangshiwen/p/3619400.html
Copyright © 2011-2022 走看看