• javascript函数篇一、理解javascript中的函数参数(arguments对象相关问题)和函数名


    本文内容:

    • 理解函数是对象,函数名是指针;
    • 理解函数的参数问题 ===> arguments对象相关

    今天看了javascript函数的相关知识,果然平时用多了各种框架,对于原生js的掌握并没那么深入,每次看都有新的收获,本篇文章和大家分享对于函数名和函数参数的理解,以及为什么JS中没有函数重载的概念。

    函数名是指向函数对象的指针
    首先要知道Javascript中的函数实际上也是对象,每个函数都是Function类型的实例而已。因为是对象,所以函数名其实和包含对象指针的其他变量没有什么区别,也是一个指向函数对象的指针。

    var obj = {}
    function a () {
    console.log(1)
    }

    如上,变量obj其实是指向一个空对象的指针,同样函数名a与变量obj并没什么不同,也是指向此函数对象的一个指针。
    **再次强调一遍,函数名仅仅是指向函数对象的指针!**
    那么下面的例子就可以很好的理解了:

    function a (num1, num2) {
        return num1 + num2
    }
    var b = a
    alert(b(1,1)) // 2
    a = null
    alert(b(1,1)) // 2

    以上代码中,首先定义了一个函数a,然后将其赋值给变量b, 因为知道了a是指向我们所定义的函数的指针,所以这个赋值操作其实做的是将a指向的地址传递给变量b,此时b也指向了我们定义的函数对象,那么调用b就会执行我们定义的函数,即便接下来改变了a的指向为一个空对象,但并不影响b的指向,也就依然能正常执行函数,输出函数结果2.过程如下:

    理解函数参数
    javascript中的函数参数与其他语言中的函数参数有所不同,javascript中的参数没有参数个数和类型的限制,也就是说,无论你定义的时候定义了几个参数,实际调用的时候依然可以传任意多个参数,甚至不传,更没有参数类型的限制。
    之所以是这样,原因是javascript中的在内部使用一个数组来表示的。函数内部接收到的始终是这个数组,不关心数组有哪些参数或者是否有参数。而在函数体内可以通过arguments来访问这个参数数组,获取到函数的每一个参数。
    arguments
    只是一个类似数组的对象,但它并不是Array的实例。它同样可以通过下面这种方式访问它的每一个元素:arguments[0],arguments[1]...同样拥有length属性,表示函数传递进来的参数个数。

    function doSomething (num1, num2) {
        if (arguments.length > 2) { // 如果函数有两个以上的参数
            console.log(arguments[2]) // 输出第三个参数
        }
    }    

    arguments获取到的函数参数与对应的函数形参的同步特性
    arguments有一个特殊的性质,就是它的值永远和对应的形参保持同步。
    举个例子就明白了,如果一个函数的参数有三个,实际调用的时候只传了两个参数,那么前两个arguments元素与形参保持同步,即共享数据并且改变时保持同步,而第三个形参与arguments[2]是不同步的。

    function fn (a, b, c) {
        console.log(a === arguments[0]) // true
        a = {name: 'zhangsan', age: 18}
        console.log(arguments[0]) // {name: 'zhangsan', age: 18}
        console.log(b === arguments[1]) // true
        arguments[1] = {name: 'lisi'}
        console.log(b) // {name: 'lisi'}
        c = 40
        console.log(arguments[2]) // undefined
        arguments[2] = '123'
        console.log(c) // 40, 可见c与arguments[2]是互不影响的
    }
    var p1 = {name: 'xiaoming', age: 6}
    var p2 = {age: 10}
    fn(p1, p2)

    **注意:没被传递参数的形参和相应的arguments元素都被赋值为undefined,就像是定义了变量,但没有被初始化一样。**
    *另外,形参与对应的arguments元素保持同步,并不代表他们是读取相同的内存空间,它们的内存空间是独立的,只是值会同步而已。*

     arguments对象三个有用属性:length、callee、properties-indexes

    1. length:真正传递的参数个数;
    2. callee:指向当前函数的引用(caller:调用当前函数的函数,两者不同以后会有介绍);
    3. properties-indexes:函数的参数值(按参数列表从左到右排列)

    arguments.callee应用如下:

    function fn(n) {
        if (n <= 1) {
            return 1
        } else {
            return n * arguments.callee(n - 1) // arguments.callee指向当前函数的引用,这里相当于是在递归调用fn()
        }
    }
    console.log(5) // 20        

    虽然使用arguments.callee消除了函数的执行与函数名的紧密耦合,不论函数名怎么改变,这里都能正确递归调用此函数。但是访问arguments是一个非常昂贵的操作,因为arguments是一个很大的对象,每次递归时都需要重新创建。影响现代浏览器的性能,还会影响闭包,所以arguments.callee并不赞成使用。

     将arguments对象转为数组
      有两种方法可以将arguments对象转为数组:

    1. Array.prototype.slice.apply(arguments);
    2. Array.from(arguments); 

    到这里对函数参数和函数名做了这些了解后,我们就可以深入理解下为什么javascript中没有函数重载了。请看下篇文章:
    [深入理解为什么javascript没有函数重载](https://www.cnblogs.com/youyang-2018/p/11706062.html)

  • 相关阅读:
    c#与JavaScript实现对用户名、密码进行RSA非对称加密
    NPOI操作EXCEL(五)——含合并单元格复杂表头的EXCEL解析
    NPOI操作EXCEL(四)——反射机制批量导出excel文件
    NPOI操作EXCEL(三)——反射机制进行excel表格数据的解析
    NPOI操作EXCEL(二)——大量不同模板时设计方式
    由一个投票算法引发的思考
    .NET WebAPI 实现图片上传(包括附带参数上传图片)
    .NET WebAPI 用ExceptionFilterAttribute实现错误(异常)日志的记录(log4net做写库操作)
    .NET WebAPI 用ActionFilterAttribute实现token令牌验证与对Action的权限控制
    js中的console
  • 原文地址:https://www.cnblogs.com/youyang-2018/p/11706056.html
Copyright © 2020-2023  润新知