高级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

 
 

转载于:https://www.cnblogs.com/zhangshiwen/p/3619400.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值