2.2函数

一、函数的定义和调用

1.JavaScript函数的本质(类型 function)

  • JavaScript将函数看做是一种类型值,与其他类型地位相同,凡是可以赋值的地方就可以使用函数。
  • 所以var a=某一个函数这种赋值方式是正确的。
  • 正因为如此JavaScript函数在使用上非常灵活

2.函数的声明
function命令:function后面跟函数名,接下来是由圆括号包围的参数列表,函数体放在花括号内部。

function print(s){
console.log(s);
}

直接使用表达式法:将函数定义直接写在等号右侧即可,这也是JavaScript将函数当成一种类型的典型表现

var print =function(s){
console.log(s);
}

3.函数调用

<script type="text/javascript">
   function sum(a,b){
    return a+b;
   }
   
   var f2=function(a,b){
    return a*b;
   }
   
   console.log(sum(5,7));//----输出为:12
   console.log(f2(5,7));//-----输出为:35
  </script>

注意事项:

  • JavaScript没有重载,如果函数名称相同,会调用后定义的。
  • 如果函数中不写return语句,或return语句后面无内容,则函数的返回值为undefined。

二、函数属性

1.函数的属性和方法

  • 在JavaScript函数中,有一些特定的元素,他们被称为属性和方法
  • 这些元素不仅有预定义的,还可以自定义,自定义的属性和方法会成为JavaScript面向对象的实现方式
  • 预定义的属性有
    name:获取函数名称
<script type="text/javascript">
   function f1(){}
   console.log(f1.name);//f1
   
   var f2=function(){}
   console.log(f2.name);//f2
   
   var f3=function myname(){}
   console.log(f3.name);//myname
</script>

length属性:返回函数预期传入的参数个数

<script type="text/javascript">
   function sum(a,b){
    return a+b;
   }
   
   var f2=function(a,b,c){
    return a*b+c;
   }
   
   console.log(sum.length);//----输出为:2
   console.log(f2.length);//-----输出为:3
</script>

toString方法:返回函数源代码(函数内部的注释也可以返回)

<script type="text/javascript">
   function sum(a,b){
     return a+b;
     }
    console.log(sum.toString());
</script>

2.函数的作用域
-----定义:作用域(scope)指的是变量存在的范围。在ES5的规范中,JavaScript只有两种作用域:一种是全局作用域,变量在整个程序中一直存在,所有的地方都可以读取;另一种是函数作用域,变量只存在函数内部。
-----函数外部声明的变量就是全局变量,他可以在函数内部读取。
-----在函数内部定义的变量,外部无法读取,称为“局部变量”。

<script type="text/javascript">
     var a;//全局变量
     function fun(){
         a=2;//若加上var则结果变为undefined
   }
   console.log(a);//输出为:undefined
   fun();
   console.log(a);//输出为:2
</script>

------函数内部定义的变量,会在该作用域内覆盖同名的全局变量(局部变量不会污染全局变量,但是局部变量命名时要谨慎)

<script type="text/javascript">
     var a=1;
     function fun(){
         var a=2;
     }
     fun();//若想要输出2---console.log(fun())且在fun()函数中要添加return a;
     console.log(a);//输出为1;若函数中的var去掉,则输出为2,局部变量污染全局变量
</script>

3.let和const
-----在ES5里只有var,在ES6中新增的定义变量的关键字let。
-----let将变量的作用域局限在“块”内,而var则将变量的作用域局限于函数内部。
-----let不能重复声明,而var可以。(写的let只能在花括号里面操作)
-----const常量

var a=1;
var a=0;//合法
let b=0;
let b=1;//非法

<script type="text/javascript">
    
   if(true){
    let a=1;
    var b=1;
   }
   console.log(b);//--输出1
   
   //等价于上面的代码
   var b;
   if(true){
    let a=1;
       b=1;
   }
   console.log(b);//--输出1
   console.log(a);//报错
  </script>

三、let实例

实例一

<script type="text/javascript">
   var a=[];
   //var i;等价于把 i 提前声明到此处
   for(var i=0;i<5;i++){
    a[i]=function(){
     console.log(i);
    }
   }
   a[1]();
   a[2]();
   a[3]();
   
   console.log("--------------------");
   
   var b=[];
   for(let j=0;j<5;j++){
    b[j]=function(){
     console.log(j);
    }
   }
   b[1]();
   b[2]();
   b[3]();
  </script>

在这里插入图片描述
重要补充说明:

  • 变量提升:当用var 声明一个变量的时候,编译器默认把声明的语句提到语句块的最前面,在哪里声明,就提到谁的前面(例如:在var a=[];后声明 var i;)
  • a[i]=functiion----在JavaScript中来说,此处的function是函数的声明,声明需要用到 i ,但是此处仅仅只是声明,没有使用;当循环结束的时候 i 等于5,所以当最后使用的时候,输出结果为5,这里的 i 是全局的,只有一个地址。
  • var修饰的变量是当前域的变量
  • let具有的特性,是一个块级元素,这里的每个 i 都有自己的地址,互不影响

实例二

<script type="text/javascript">
   console.log(a);
   var a=1;
   console.log(b);
   let b=2;
  </script>

等价于上面的代码

<script type="text/javascript">
   var a;
   console.log(a);
       a=1;
   console.log(b);
   let b=2;
  </script>

在这里插入图片描述
补充说明:

  • 产生这种效果的原因是var的变量提升效果

实例三

<script type="text/javascript">
   var a=1;
   function fun(){
    console.log(a);
    if(false){
     var a=2;//重新定义了局部变量var a,变量提升到了域的顶部
    }
   }
   fun();//结果为undefined
  </script>

等价于下面的代码:

<script type="text/javascript">
   var a=1;
   function fun(){
    var a;
    console.log(a);
    if(false){
     a=2;
    }
   }
   fun();
  </script>

四、arguments

1.函数的参数

  • 定义:函数运行的时候,有时候需要提供外部数据,不同的外部数据会得到不同的结果,这个外部数据就叫做参数。
  • 函数参数不是必须的,JavaScript中允许省略参数
  • 注意:只有参数列表中靠后的参数可以省略,靠前的不能省略,如果想省略必须现实输入undefined。
  • JavaScript中函数没有重载
<script type="text/javascript">
   function f(a,b){
    return a;
   }
   f(undefined,2);//如果此处不写undefined省略,会报错
   console.log(f(,2));//报错
   console.log(f(1,2));//1
   console.log(f(2));//2
   console.log(f(1,2,3));//1
  </script>

2.arguments对象

  • 定义:由于在JavaScript允许函数有不定数目的参数,所以需要一种机制,可以在函数体内部读取所有参数,这就是arguments对象的由来。
  • arguments对象包含了函数运行时的所有参数,arguments[0]就是第一个参数,arguments[1]就是第二个参数,以此类推。这个对象只有在函数体内部,才可以使用。
  • 需要注意的是arguments虽然很像数组,但它是一个对象。数组专有的方法(比如slice和forEach),不能在arguments对象上直接使用
  • 如果要让arguments对象使用数组方法,真正的解决方法是将arguments转为真正的数组。
  • arguments输出的是传递的参数,并且以数组的形式,length输出的是函数定义的参数的个数
<script type="text/javascript">
   var f=function(one){
    console.log(arguments[0]);
    console.log(arguments[1]);
    console.log(arguments[2]);
    console.log(arguments[3]);
   }
   f(4,2,3)
  </script>

在这里插入图片描述
3.借助arguments对象,模拟函数重载

<script type="text/javascript">
   var f=function(a,b){
    if(arguments.length==2){
     return a+b;
    }else{
     return b;
    }
   }
   console.log(f(1,2));//返回值为3
   console.log(f(1,2,3));//返回值为2
  </script>

4.callee属性
arguments对象带有一个callee属性,返回它所对应的原函数

<script type="text/javascript">
   var f=function(a,b){
    console.log(arguments.callee===f);
   }
   f();//true
   
  </script>

五、闭包

1.闭包
有权访问另一个函数作用域内变量的函数都是闭包。闭包就是一个函数引用另一个函数的变量,因为变量被引用着所以不会被回收,因此可以用来封装一个私有变量。

//未使用闭包
<script type="text/javascript">
   function autoCount(){
    let count=0;
    console.log(count);
    return count+=1;
   }
   var counter=autoCount;
   counter();//输出0
   counter();//输出0
   counter();//输出0
  </script>
//使用闭包,变量不会被销毁
<script type="text/javascript">
   function autoCount(){
    let  count=0;
    return function(){
     console.log(count);
     return count+=1;
    }
   }
   var counter=autoCount();
   counter();//输出0
   counter();//输出1
   counter();//输出2
  </script>

六、IIFE

1.立即调用的函数表达式(IIFE)

  • 在JavaScript中,圆括号()是一种运算符,跟在函数名之后,表示调用该函数。比如print()就表示调用print函数。
  • 有时需要在定义函数之后,立即调用该函数。这时,不能在函数的定义之后加上圆括号,这会产生语法错误。解决方法有下面两种

方法一:(function(形参){/* code /}(实参))
方法二:(function(形参){/
code */})(实参)

<script type="text/javascript">
   (function(value){
    alert(value);
   })("HELLO IIFE");
  </script>

好处:一是不必为函数命名,避免污染全局变量;二是IIFE内部形成了一个单独的作用域,可以封装一些外部无法读取的私有变量。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值