• Js整理备忘(05)——函数基础(一)


    概念:函数(function)可以简单地定义为“具有可执行代码的对象”。

    • 具体地说,函数是定义一次却可以调用或执行任意多次的一段Javascript(以下简称Js)代码。
    • 函数可以指定参数(arguments),常用来参与运算得到函数的返回值,返回值即为函数调用表达式的值。
    • 在对象内部定义的函数叫做方法(method),对象在调用方法时,该对象也会作为方法的一个隐式参数。

    类型:对一个函数进行typeof()运算,返回类型为 function

    • 但是函数定义中又说,“函数是……的对象”,怎么回事??——唉,这只能说是Javascript语言的宽松特性了。而且,函数与对象的关系比数组与对象间的关系更复杂更微妙,需要用心慢慢感受,呵呵(^_^)。 后面计划专门用一篇来说明函数与对象的微妙关系

    特点:

    • 函数最重要的特点就是能够被调用。
    • 尽管定义函数时可以指定固定数目的参数,但调用时,允许传递任意数目的实际参数。

    1、函数的创建(定义)

    (1)函数直接量

    ——函数直接量是一个表达式,它通常定义为一个匿名函数,直接赋给一个变量,或者直接用作某个函数的参数。例如:

    var f=function(x){ return x*x;}; //整体是个语句,“=”右边的表达式是一个函数直接量

    当然,也可以给函数直接量指定一个函数名,如下:

    var f=function fn(x){ return x;};//这样定义完全没有问题

    (2)function语句

    ——只是单纯定义一个函数

    例如:

    function print(msg) {
        document.write(msg+"<br/>");
    }

    该函数名为“print”,有一个参数msg,函数体中没有return语句,即没有返回值,或者说返回“undefined”。

    调用时,可以直接写:print("hello");

    再看个例子:

    function distance(x1, y1, x2, y2) {
        var dx = x2 - x1;
        var dy = y2 - y1;
        return Math.sqrt(dx * dx + dy * dy);
    }

    很明显,该函数计算两点之间的距离,并返回计算后的数值。

    可以如此调用:var d=distance(1,1,4,5);//d=5

    (3) 使用Function对象创建函数

    ——Function是一个构造函数,它用来创建函数。它是Js中比较重要的一个概念,尽管真正用它创建函数的情况并不多见,但是概念上很值得好好了解。

    用法:var f=new Function("x","y","return x+y;");//该方法比较笨拙,真正创建函数时一般不使用

    相当于function f(x,y){return x+y;}

    2、函数的参数(arguments)

    (1)可选参数

    当实际传递的参数数目少于定义时声明的参数数目,那么其他参数就为undefined值。

    注意:由于这个特性,设计函数时应该把可选的参数放到参数列表的末尾。否则就有可能要显式传递undefined或者null值作为其中一个参数。

    (2)Arguments对象

    本文开头特点中也提到,向函数传递任意数目的参数都是合法的,不管函数定义时声明了几个参数。这一特点要归功于函数中的arguments属性,它引用一个Arguments对象,这是一个“类似数组的对象”。Arguments对象允许存取所有的实际参数,使用下标来访问这些实际参数,其length属性表示实际参数的个数。

    arguments对象的存在很有意义,例如,可以编写一个可变参数函数。例如求一系列数字中的最大值(数字的数目可以是不确定的)。

    要始终明确:

    • arguments 并非数组,它是一个Arguments对象。将它看作具有一些带编码的属性的对象更加合适。
    • Arguments还有一个特性,arguments通过下标可以访问这些参数的值,也可以改变参数的值。
    function f(x) {
        print(x);
        arguments[0] = null;    // x的值也会被改变
        print(x);               // 输出null
    }
    f("hi",123);//调用函数f

    也就是说该函数中的arguments[0]就相当于参数变量x,一个值改变则另一个也跟着改变。

    这一特性同时也说明了arguments不是普通意义上的数组。普通的数组若其中某个元素最初跟某个变量的值相等,那么之后改变该元素的值应该不会导致变量的值改变。

    • Arguments还有一个属性callee。用来引用当前正在执行的函数。可以用来允许为命名的函数递归调用自身。

    (3)参数的类型

    由于Js的宽松特性,函数在声明时不需要指明参数的类型,并且调用时对实际传递的参数值也不执行类型检查。

    有时候定义函数的时候会希望参数是某种类型,这时可以在参数中用注释指明类型,增强代码的可读性,例如:

    function fn(/*number*/n, /*string*/s /* ,optional...*/) {
        /* code here */
    }

    函数fn第一个参数应该为number类型,第二个参数应该为string类型,剩下的参数可以是有选择的(optional)。

    3、函数的应用

    (1)作为数据

    Js中函数不只是一种语法,还可以用作数据,此时通常是指具有返回值的函数,作为数据使用主要体现在:

    • 把函数赋给一个变量,例如:
    function square(x) { return x * x; } //先定义一个函数
    var a = square(4);                   //调用函数,将返回值赋给变量
    • 存储在对象的属性中,例如:
    var o = {}; //定义一个对象                                
    o.square = function(x) { return x * x; };//给对象添加属性square,赋给它一个函数,此时square就作为对象的方法
    y = o.square(4);//调用对象的方法
    • 存储在数组的元素中
    var a = [];
    a[0] = function(x) { return x * x; }//将函数赋给数组的第一个元素
    a[2] = a[0](12);//如此调用,a[2]值为144
    • 作为参数传递给某个函数

    可参考数组方法sort()时所举的例子,不再赘述。

    (2)作为方法

    即相当于(1)中所讲的将函数存储在对象的属性中的做法。函数此时被称为该对象的方法。

    注意:在方法体中可以用this关键字来引用当前(调用这个方法的)对象。(有点拗口,不过很重要)

    var cal = {
        x: 100,y: 50,
        add: function() {
            var result = this.x + this.y; //这里的this相当于当前对象cal的引用,可以调用该对象的属性x和y
            return this.result;
        }
    };

    当一个函数作为函数而不是作为对象的方法调用时,这个this则引用全局对象。

    (3)作为构造函数(constructor function)创建对象

    构造函数是用来创建对象的一个函数。例如:

        function point(x, y) { this.x = x; this.y = y; } //定义一个构造函数,利用this给该构造函数创建的对象添加属性。
        var p = new point(2, 3);  //调用构造函数point,创建点对象p,此时point中的this就是p对象的引用,即p.x=2,p.y=3。
    //相当于p={x:2,y:3}
        var q = new point(-1, -3);//同样的构造函数创建一个新对象q,这时point中的this就是q对象的引用,即q.x=-1,q.y=-3。
    //相当于q={x:-1,y:-3}

    对象创建过程可以这么理解,用 new 运算符创建一个新的对象,然后调用构造函数,把新的对象作为this关键字的值来传递。

    注意:这里一定要使用new运算符,否则就不是创建对象,例如:

    var p=point;只是相当于将函数的引用赋给另一个变量p,即此时p跟point代表一个函数的引用。

    var p=point(1,1);只是相当于执行函数,并将返回值赋给变量p,该语句执行后p为undefined,因为调用的函数point没有设置返回值。

    ——了解面向对象的话,可以看出,构造函数的概念很像面向对象语言中的“类”的概念。

    此处不再细说,后面讲函数与对象的微妙关系时会再谈到构造函数的具体使用。

    4、函数的属性和方法

    当typeof()运算符用于一个函数的时候,返回字符串“function”,但是函数确实是一种特殊的对象(具有可执行代码的对象)。

    既然是对象的一种,那么就可以具有属性和方法。

    就像Date对象一样,Date是构造函数(本身的类型是function),跟new运算符一起使用可以创建新的Date对象,创建的对象实例的类型是object,新对象一旦创建便拥有了Date对象的所有属性和方法。

    (1)属性length

    函数的length属性是指该函数声明的形式参数的个数。而前面提到的函数体中的arguments.length是指调用函数时实际参数的个数。

    例如,以下函数check()可以用来检测当前被调用的函数,形参与实参数目是否相等。

    <script language="javascript" type="text/javascript">
        function check(args) {
            var actual = args.length;           //实参个数
            var expected = args.callee.length;  //当前执行的函数的形参个数
            //callee是Arguments的属性,引用当前执行的函数,本文介绍Arguments对象时提到
            if (actual != expected) {
                alert("传入的参数个数不匹配,请检查!");
            }
        }
        //在函数中调用check()
        function f(x, y, z) {
            check(arguments); //arguments是函数内部属性
            document.write(x + y + z);
        }
        //调用函数f() 
        f(1, 2);    //<1>弹出提示框,页面输出非数值NaN,因为z参数此时为undefined
        f(1, 2, 3); //<2>正常执行,页面输出6
    </script>

    (2)属性prototype

    每个函数都有一个prototype属性,他引用的是预定义的原型对象。它在定义新的对象类型时起着非常重要的作用,后面还需要详细说明。

    (3)方法apply()和call()

    ——这也是一个比较有趣的方法。ECMAScript规范给所有的函数都定义了这两个方法。

    • 这两个方法可以像调用其他对象的方法一样调用函数。例如,要把两个参数传给函数f(),并将它作为对象o的方法调用,如下:
    f.call(o, 123, "asd");
    这句代码相当于:
    o.m = f;        //将函数赋给对象o的属性m,则m成为o的一个方法
    o.m(123, "asd");//调用o的方法m
    delete o.m;     //清除方法m
    • 两个方法作用相同,只不过传参方式不同

    例如,上面的例子若使用apply()方法的话,调用方式为

    f.apply(o, [123, "asd"]);其中的参数是存放在数组中的。

    当一个函数需要接受很多个参数时,可以将这些参数放到一个数组中,然后调用该函数的apply方法,传递一个数组作为参数。

    ——先写到这里,下一节计划学习函数基础(二)——函数的作用域和闭包。

  • 相关阅读:
    使用NDK开发SQLite3
    SQL Server 2005 Default Trace (默认跟踪)
    MySQL 获得当前日期时间 函数
    利用UltraISO写入U盘安装系统,条件:电脑支持USBHDD ,U盘容量足够
    Sicily 1157 The hardest problem
    Histogram of oriented gradients(HOG)
    IE中的CSS3不完全兼容方案
    MySQL如何查询两个日期之间的记录
    查找某个字段最大值的记录 SQL 语句
    用 jQuery 实现页面滚动(Scroll)效果的完美方法
  • 原文地址:https://www.cnblogs.com/gppblog/p/1647497.html
Copyright © 2020-2023  润新知