JavaScript(5)__Js基础<函数>

1:函数的概述

函数就是一段可以反复调用的代码块。函数还能接受输入的参数,不同的参数会返回不同的值。


2:函数的声明

1:具有函数

function命令声明的代码区块,就是一个函数。function命令后面是函数名,函数名后面是一对圆括号,里面是传入函数的参数。函数体放在大括号里面。


2:匿名函数(函数表达式)


这种写法将一个匿名函数赋值给变量。这时,这个匿名函数又称函数表达式(Function Expression),因为赋值语句的等号右侧只能放表达式


3:函数的重复声明

如果同一个函数被多次声明,后面的声明就会覆盖前面的声明



4:函数的属性

  name:返回函数的名字


length:形参的个数



5:参数的省略

函数参数不是必须的,Javascript允许参数省略,但是,没有办法只省略靠前的参数,而保留靠后的参数。如果一定要省略靠前的参数,只有显式传入undefined。



被省略的参数的值就变为undefined。需要注意的是,函数的length属性与实际传入的参数个数无关,只反映函数预期传入的参数个数。



6:传值方式(基本类型,复合类型)

函数参数如果是原始类型的值(数值、字符串、布尔值),传递方式是传值传递(passes by value)。这意味着,在函数体内修改参数值,不会影响到函数外部。


如果函数参数是复合类型的值(数组、对象、其他函数),传递方式是传址传递(pass by reference)。也就是说,传入函数的原始值的地址,因此在函数内部修改参数,将会影响到原始值。



7:同名参数

如果有同名的参数,则取最后出现的那个值。


调用函数f的时候,没有提供第二个参数,a的取值就变成了undefined。这时,如果要获得第一个a的值,可以使用arguments对象。


8:arguments对象

由于JavaScript允许函数有不定数目的参数,所以我们需要一种机制,可以在函数体内部读取所有参数。这就是arguments对象的由来。

arguments对象包含了函数运行时的所有参数,arguments[0]就是第一个参数,arguments[1]就是第二个参数,以此类推。这个对象只有在函数体内部,才可以使用。



9:函数返回值

函数的返回值用return返回,如果没有return,那么函数返回值undefined

function sum(x,y) 

       {                   

              return x+y;   //函数返回值:return   --  输出(做完事后能得到什么)

                            //注:无return时,返回undefined  ,  return 后面语句不执行 

       }    

       alert(sum(3,5));  //传参调用


10:函数的返回值可以是函数

function fn(a){

              alert('fn run');

         return function(b){

             alert('run ..');

             returna+b;

         }

       }

       alert(fn(10)(20));


11:return后如果换行系统会默认加上分号

下面程序运行后,返回值是什么?

       functionfoo(){

              return  

               {

                   bar: "hello"

              };

       }

  console.log(foo());    


     


12:需求练习

写一个按照下面方式调用都能正常工作的 sum 方法

          console.log(sum(2,3));     // Outputs 5

            console.log(sum(2)(3));   // Outputs 5

function sum2(x, y) {
    if (arguments.length === 2) {
        return x + y;
    }
    return function (a) {
        return x + a;
    }
}
console.log(sum2(4, 5));
console.log(sum2(4)(5));

function sum3() {
    var first = arguments[0];
    if (arguments.length === 2) {
        return (arguments[0] +arguments[1]);
    } else {
        return function (sec) {
            return first + sec;
        }
    }
}



13:函数练习

1:用户录入两个数据,返回两个数中的较大值

function getMax(x, y) {
    /*if(x>y) {
     return x;
     }else {
     return y;
     }*/
    return x > y ? x : y;
}
var num1 = prompt("第一个数");
var num2 = prompt("第二个数");
console.log(getMax(num1, num2));

 

2:用户录入两个数据,比较两个数是否相等

function isEqual(x, y) {
    return x === y ? true : false;
}
console.log(isEqual(num1, num2));

 

3:实现字符串的indexOf函数

function myIndexOf(str, c) {
    for (var i = 0; i < str.length;i++) {
        if (c == str[i]) {
            return i;
        }

    }
    return -1;
}
var str = "javaSrcipt";
var index = myIndexOf(str, "h");
if (index != -1) {
    console.log("您要找的字符的下标是" + index);
} else {
    console.log("没有找到该字符");
}

 


 

4:实现一个函数,判断字符串是否是回文

function isHuiwen(str) {
    str = str.toLowerCase();
    var arr = str.split("");
    return (str ===arr.reverse().join(""));
}
var b = isHuiwen("level");
if (b) {
    console.log("是回文")
} else {
    console.log("不是回文");
}

 

5:实现数组的join函数

function myJoin(arr, c) {
    var empty = "";
    for (var i = 0; i < arr.length;i++) {
        empty += arr[i];
        if (i == arr.length - 1) {
            break;
        }
        empty += c;
    }
    return empty;
}
var arr = [4, 5, 6];
console.log(myJoin(arr, "*"));

 

6:实现数组的map函数

function myJoin(arr, c) {
    var empty = "";
    for (var i = 0; i < arr.length;i++) {
        empty += arr[i];
        if (i == arr.length - 1) {
            break;
        }
        empty += c;
    }
    return empty;
}
var arr = [4, 5, 6];
console.log(myJoin(arr, "*"));


 

7:数组去重

function isHave(arr, x) {
    for (var i = 0; i < arr.length; i++) {
        if (x == arr[i]) {
            return true;
        }
    }
    return false;
}
function delRepeat(arr) {
    var n = [];
    for (var i = 0; i < arr.length;i++) {
        if((isHave(n,arr[i]))==false) {
            n[n.length] = arr[i];
        }
    }
    return n;
}
var arr1 = [3, 44, 5, 5, 6, 6, 7];
console.log(delRepeat(arr1));


14:函数的递归

函数可以调用自身,这就是递归(recursion)。下面就是通过递归,计算斐波那契数列的代码。


求x的阶乘

 function getX(x) {

       if(x<=1) return 1;

       return x*getX(x-1);

    }

 

   console.log(getX(4));



15:函数作用域

1:作用域(scope)指的是变量存在的范围。Javascript只有两种作用域:一种是全局作用域,变量在整个程序中一直存在,所有地方都可以读取;另一种是函数作用域,变量只在函数内部存在。

2:在函数外部声明的变量就是全局变量(global variable),它可以在函数内部读取。


在函数内部定义的变量,外部无法读取,称为“局部变量”(local variable)。

 

3:函数内部定义的变量,会在该作用域内覆盖同名全局变量。



注意,对于var命令来说,局部变量只能在函数内部声明,在其他区块(if,for)中声明,一律都是全局变量。

 

4:如果变量在函数内没有声明(没有使用 var 关键字),该变量为全局变量。

// 此处可调用 b变量

function myFunction() {

    b ="haha";

    // 此处可调用 b 变量

}




5:函数作用域内部也会产生“变量提升”现象。var命令声明的变量,不管在什么位置,变量声明都会被提升到函数体的头部。


小练习:

var v='Hello World';

(function(){

alert(v);

var v='javascript';

})()

//等价于

 

var v='Hello World';

(function(){

var v;

alert(v);

v='haha';

})() 



16:作用域链

函数嵌套--> 形成链条 --> 变量回溯(当前没有,沿着链条追查上家)

 var  age = 30;

        function fn(){

              var age = 50;

               function fn1(){

                     varage = 40;

                     functionfn2(){

                            //var age = 50;

                         console.log(age);  //变量的回溯机制(当前没有,追查上家)

                            //var age = 90;    //声明定义的提升。

                     }           

                     fn2();

               }   

               fn1();

        }

        

        fn();

 

 var num=5;

    functionfunc1(){

        varnum=3;

        varage =4;

       function func2(){

           console.log(num);

           var num ='ivan';

           function func3(){

               age =6;

            }

           func3();

           console.log(num);

           console.log(age);

        }

       func2();

    }

    func1();


易错点:

函数本身也是一个值,也有自己的作用域。它的作用域与变量一样,就是其声明时所在的作用域,与其运行时所在的作用域无关。


17:闭包

闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现。

要理解闭包,首先必须理解变量作用域。前面提到,JavaScript有两种作用域:全局作用域和函数作用域。函数内部可以直接读取全局变量。但是,在函数外部无法读取函数内部声明的变量。


如果出于种种原因,需要得到函数内的局部变量。正常情况下,这是办不到的,只有通过变通方法才能实现。那就是在函数的内部,再定义一个函数。


上面代码中,函数f2就在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的。但是反过来就不行,f2内部的局部变量,对f1就是不可见的。这就是JavaScript语言特有的”链式作用域”结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。

既然f2可以读取f1的局部变量,那么只要把f2作为返回值,我们不就可以在f1外部读取它的内部变量了吗!


函数f1的返回值就是函数f2,由于f2可以读取f1的内部变量,所以就可以在外部获得f1的内部变量了。



闭包就是函数f2,即能够读取其他函数内部变量的函数。由于在JavaScript语言中,只有函数内部的子函数才能读取内部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”。闭包最大的特点,就是它可以“记住”诞生的环境,比如f2记住了它诞生的环境f1,所以从f2可以得到f1的内部变量。在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁


闭包的最大用处有两个,一个是可以读取函数内部的变量,另一个就是让这些变量始终保持在内存中,即闭包可以使得它诞生环境一直存在。请看下面的例子,闭包使得内部变量记住上一次调用时的运算结果


为什么会这样呢?原因就在于inc始终在内存中,而inc的存在依赖于createIncrementor,因此也始终在内存中,不会在调用结束后,被垃圾回收机制回收。

 

start是函数createIncrementor的内部变量。通过闭包,start的状态被保留了,每一次调用都是在上一次调用的基础上进行计算。从中可以看到,闭包inc使得函数createIncrementor的内部环境,一直存在。所以,闭包可以看作是函数内部作用域的一个接口。

 

闭包的作用:   闭包:通过引用访问函数内的函数,实现信息的驻留。

               驻留:信息保持(引用在,空间则不销毁)





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值