美文网首页
函数初识

函数初识

作者: lyp82nkl | 来源:发表于2019-06-19 00:45 被阅读0次

    函数的5种声明方式

    具名函数

     function f(x,y){
         return x+y
     }
     f.name // 'f'
    
    • 具名函数的函数名也是变量名
    • 函数里面如果只写return和return undefined是一个意思,另外函数返回0、 ' '、 NaN 、undefined、 null都等同于返回false
    • function x(val1,val2){return}等同于function x(val1,val2){return undfined}

    匿名函数

    • 不能单独使用,必须先声明一个变量,把他赋值给变量
     var f
     f = function(x,y){
         return x+y
     }
     f.name // 'f'
    

    具名函数赋值

    • 采用函数表达式声明函数时,function命令后面不带有函数名。如果加上函数名,该函数名只
     var f
     f = function f2(x,y){ return x+y }
     f.name // 'f2'
     console.log(f2) //f2 is not defined
    

    window.Function

    var f = new Function('x','y','return x+y')
    
    • 如果你用new Function声明一个函数,那么这个函数没有名字的,也就是匿名函数

    箭头函数

     var f = (x,y) => {
         return x+y
     }
    f(1,2)//调用方法函数名(参数1,参数2)    3
    //如果函数体内只有一条语句,大括号和return可以省略,也就是说在不写大括号的情况下,它默认就return
     var sum = (x,y) => x+y
    //如果函数只有一个参数,小括号可以省略
     var n2 = n => n*n
    

    函数的执行

    var z;
    function f2(){
        console.log(z)
    }
    z=1;
    f2.call()//1
    

    上面的代码函数调用后打印出来的z是1,而不是undefined,是因为在函数f2声明的时候并未获取和打印出z这个变量,而是在f2调用的时候才去获取的,就相当于只要在函数调用的时候打印的z都是与函数调用这段代码最近的那个z。也就是说一个函数里面获取一个变量,是在函数调用之后才去获取的(获取的变量是与函数调用这个代码前面的最新一次的变量值),而不是函数声明的时候就获取。

    上面的代码其实你也可以看成:

    var z;
    z=1;
    function f2(){
        console.log(z)
    }
    f2.call()//1
    

    将执行的函数赋值给一个变量

    • 将一个执行的函数赋值给一个变量,它会先执行一下函数内部的语句,然后将返回值赋值给变量,之后执行这个变量操作的时候,这个变量的值都等于函数的返回值,而不会再去执行函数内部的语句。
    function fn(){
        console.log('aaa');
        return 'zzz'
    }
    var result = fn()  //'aaa'
    result  //'zzz'
    
    • 上面的代码将执行的fn函数赋值给result,fn函数先执行了它内部的代码,打印出了'aaa',然后将返回值'zzz'赋值给了result,所以此时var result = 'zzz',之后获取result变量得到的值都是'zzz'

    如何调用函数

    函数到底是什么?
    • 函数就是一段可以反复调用的代码块。
    • 函数是一个对象,这个对象可以执行一段代码。
    • 可以执行代码的对象就是函数。
    var obj = {
      //这里的test就是一个方法,也可以说是函数
      test: function(){
        console.log('zzz')
      }
    }
    //方法(函数)调用
    obj.test()
    

    函数传参

    • 函数参数如果是原始类型的值(数值、字符串、布尔值),传递方式是传值传递(passes by value)。这意味着,在函数体内修改参数值,不会影响到函数外部。
    var p = 2;
    
    function f(p) {
      p = 3;
    }
    f(p);
    
    p // 2
    

    上面代码中,变量p是一个原始类型的值,传入函数f的方式是传值传递。因此,在函数内部,p的值是原始值的拷贝,无论怎么修改,都不会影响到原始值。

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

    var obj = { p: 1 };
    
    function f(o) {
      o.p = 2;
    }
    f(obj);
    
    obj.p // 2
    

    上面代码中,传入函数f的是参数对象obj的地址。因此,在函数内部修改obj的属性p,会影响到原始值。

    function fn(obj){
        obj.name = 'ff'
        obj = new Object()
        obj.name = 'man'
    }
    var person = new Object()
    fn(person)
    console.log(person.name) //'ff'
    

    1.上面代码因为是将一个引用类型作为参数,所以传入的是一个引用地址(ADDR 26),也就是形参obj的值实际上就是person的引用地址
    2.然后对这个ADDR 26添加一个name属性obj.name = 'ff'
    3.重新对形参obj进行赋值,指向另一个内存地址(ADDR 34)
    4.在ADDR 34上添加name属性obj.name='man'
    5.所以最后person.name也就是person的引用地址(ADDR 26)里的name,也就是‘ff’

    f()与f.call()

    function f(x,y){return x+y};
    f.call(undefined,1,2)   //3
    //相当于 f(1,2)
    

    f 与 f.call()区别:
    f 指的是这个对象
    f.call() 是执行这个对象的函数体

    this和arguments

    function f(){
        'use strict'
        console.log(this)
        console.log(arguments)
        return undefined
    }
    f.call(1,2,3) // this 为 1,arguments 为 [2,3]
    
    • call 的第一个参数可以用this得到
    • call 后面的参数可以用arguments得到


    上面的函数f里面写入了打印this和arguments两条语句;当执行f.call(undefined,1,2)命令时,得到this是window(chorme浏览器显示的大写的Window其实是小写的window),arguments(实参)是一个伪数组,里面有1和2两个值,这里注意为什么this不是undefined,因为默认情况下this都会变成window,所以要想得到undefined就要开启严格模式

    上面的代码使用了 ‘use strict’ 会变成严格模式。开启严格模式就不会乱改 this ,那么 this 原本的值就会打印出来。这样再给 undefined 真的是 undefined ,不会变成window。

    f.call(1)     //1    
    f.call('sss')  // sss
    

    this 就是 call 的第一个参数

    伪数组:如果你的proto(原型链中)没有Array.prototype这一环,就是伪数组。同时你的原型链的原型链也不是Array.prototype,整个原型链中跟Array.prototype没有一点 关系,就是完完全全的伪数组。
    arguments 的proto 直接指向了 object.prototype ,没有Array.prototype这一环,所以是伪数组。

    • call 的第一个参数是this,call 后面的参数是arguments。
    • 实际上可以用 arguments 全包起来,但是为了满足长得像 java 这个需求,所以设计者当初设计的时候临时加了一个 this来表示第一个参数 。

    对象中的函数

    • 属性方法里面直接调用一个和属性方法同名的函数,这个函数肯定不是这个属性方法,而是变量
    var init=function(){
      console.log('aaa')
    }
    var obj = {
      init: function(){
        console.log('zzz');
        //这里的init是上面的变量init,而不是属性init,因为对象里的属性必须对象.属性,而不能直接写属性
        init()
      }
    }
    
    obj.init()
    //zzz
    //aaa
    

    同名参数

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

    function f(a, a) {
     console.log(a);
    }
     
    f(1, 2) // 2
    

    上面代码中,函数f有两个参数,且参数名都是a。取值的时候,以后面的a为准,即使后面的a没有值或被省略,也是以其为准。

    function f(a, a) {
     console.log(a);
    }
     
    f(1) // undefined
    

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

    function f(a, a) {
     console.log(arguments[0]);
    }
     
    f(1) // 1
    
    var a = (1,2)
    a  //2
    

    上面的代码a的值是2,多个值用小括号括起来,但取值的时候总是以后面的为准

    设置默认参数值

    function b(obj,str='z'){
        return{
            obj,str
        }
    }
    

    上面的函数b里面有两个参数,其中第二个参数str,写成了str='z'意思是如果你不传第二个参数,它默认就相当于你传了一个'z'

    //调用b函数,不传入第二个参数,str就是默认的'z'
    b({name:'ff'})
    
    //当调用函数时传入第二个参数,那个str就会是你传入的值
    b({name:'ff'},'fangfang')
    

    另外如果函数表达式中需要传参,而你调用的时候没有传,那么这个参数就是undefined,可以通过参数是否等于undefined来判断有没有传参数

    相关文章

      网友评论

          本文标题:函数初识

          本文链接:https://www.haomeiwen.com/subject/puqcqctx.html