zoukankan      html  css  js  c++  java
  • JavaScript快速入门笔记(6):函数

    本系列随笔是本人的学习笔记,初学阶段难免会有理解不当之处,错误之处恳请指正。转载请注明出处:https://www.cnblogs.com/itwhite/p/12218038.html

    函数定义

    示例:

    function foo(a, b, c) {  // 注意: 参数名不需要 var、let、const 等关键字
        return a + b * c;
    }

    我们也可以像C/C++等语言一样,为函数参数指定默认参数值(调用时,若省略未指定默认参数的参数,则其默认为 undefined),例如:

    function foo(a, b, c = false) {
        return [String(a), String(b), String(c)].toString();
    }
    console.log(foo('abc', 123, true)); // abc,123,true
    console.log(foo('abc', 123));       // abc,123,false
    console.log(foo('abc'));            // abc,undefined,false,JavaScript 中即使没有指定默认参数的参数,调用时也可以省略,其默认值为 undefined

    不定参数

    JavaScript 还支持不定参数,在函数中我们可以通过“参数对象” arguments 这个标识符来访问不定参数(参数对象类似与数组,可以通过下标访问参数,同时它还包含 length、callee、caller 等属性),例如:

    function foo() {
        for (var i = 0; i < arguments.length; i++) {
            console.log(arguments[i]);
        }
    }
    foo(1, 2, 3);

    参数对象 arguments 中的 callee 对于匿名函数的递归调用相当有用,例如:

    var foo = function(n) {
        console.log(n);
        if (n > 0) {
            arguments.callee(n - 1);
        }
    };
    foo(5); // 输出 5 4 3 2 1 0
    View Code

    另外,ES6 还引入了 rest 参数(以“...变量名”的形式书写),用于获取函数的多余参数(以数组形式存放),这样就可以不使用 arguments 对象了,例如:

    function foo(a, b, ...others) {
        console.log(arguments.constructor);      // 1
        console.log(a);      // 1
        console.log(b);      // 2
        console.log(others); // [3, 4, 5]
    }
    foo(1, 2, 3, 4, 5);

    箭头函数

    JavaScript 中还支持一种简化版的函数定义方式,例如:

    const foo = (x, y) => { return x * y }; // 这里也可用 var ,但 const 更安全(C/C++里挺烦const的,呵呵~~)
    console.log(foo(2, 3)); // 6
    const bar = (x, y) => x * y; // 可以省略{} 和 return 关键字
    console.log(bar(2, 3)); // 6

    箭头函数中不能使用 this ,因此最好不要作为成员函数的定义方式。

    函数对象的属性

    函数本身也是一个对象,它本身也包含一些属性,例如:

    function foo(x, y, z) {
        console.log(foo.name);        // 输出 "foo",name 属性标识函数名
        console.log(foo.length);      // 输出 3,length 属性标识函数参数(形参)个数
        console.log(arguments.length) // 输出 2,通过 arguments 对象属性可以获取实参个数
    }
    foo(1, 2);

    函数调用形式

    JavaScript 中函数的几种调用形式如下:

    • 作为函数调用:以函数的形式直接调用,例如:foo(),被调函数体中 this 指针指向全局对象;
    • 作为方法调用:以对象方法的形式进行调用,例如:o.bar(),被调函数体中 this 指针指向对象 o ;
    • 作为构造函数:以构造函数的形式进行调用,例如:new Quz(),被调函数函数体中 this 指向新创建的对象;
    • 通过 call() 或 apply() 方法间接调用 

    函数调用与方法调用

    JavaScript 中通常将 foo() 这种调用方式称为“函数调用”,而将 o.bar() 这种调用方式称为“方法调用”(bar() 也称作是对象 o 的方法),其区别是:

    • 使用“函数调用”时,被调函数的函数体中 this 指针指向“全局对象”(通常是 window 对象)
    • 使用“方法调用”时,被调函数的函数体中 this 指针指向对象 o (即调用对象)

    示例(注意:即便是嵌套函数,若不使用“方法调用”的形式,也不会继承调用者的 this 值):

    var x = 123;
    var o = {
        x: 456,
        foo: function() {
            console.log(this.x);     // 456
            var that = this;
            function bar() {
                console.log(this.x); // 123,以函数形式调用,嵌套函数不会从条用者中继承 this
                console.log(that.x); // 456
            }
            bar();      // 以函数的形式调用,则输出 123 和 456
            this.bar = bar;
            this.bar(); // 以方法的形式调用,则输出 456 和 456
        }
    };
    o.foo();  // 以方法的形式调用,将按上述注释中的描述输出
    var foo = o.foo;
    foo(); // 以函数的形式调用,将全部输出 123

    方法链

    当调用的方法返回一个对象,通过这个对象还可以条用其它方法,这种方法调用序列便形成一条“方法链”。例如:我们可以让不需要其它返回值的方法返回 this 指针,这样便可以形成“链式调用”的编程风格,示例:

    var o = {
        foo: function() {
            console.log("foo() is called");
            return this;
        },
        bar: function(x,y) {
            console.log("bar(" + x + "," + y + ") is called");
            return this;
        },
        quz: function() {
            console.log("quz() is called");
            return this;
        }
    };
    o.foo().bar(1,2).quz();

    call() 和 apply()

    在 JavaScript 中任何函数都可以作为任何对象的方法(成员函数)来调用,例如:

    // 示例一:普通函数作为某个对象的方法来使用
    var o = {
        x: 123
    };
    function foo() {
        console.log(this.x);
    }
    o.foo = foo;
    o.foo();    // 123
    
    // 示例二:成员函数作为别的对象的方法来使用
    var c = {
        x: 456,
        bar: function() {
            console.log(this.x);
        }
    };
    c.bar();    // 456
    o.bar = c.bar
    o.bar();    // 123
    View Code

    从上面的示例中可以看到,要将某个函数作为某个对象的方法来使用,需要设置该对象的相应属性指向该函数。为了简化这个过程,JavasScript 中为每个函数(对象)都提供了 call() 和 apply()等方法,例如:

    var o = {
        x: 123
    };
    function foo(a, b, c) {
        console.log(this.x, a, b, c);
    }
    foo.call(o, 4, 5, 6);       // 输出:123 4 5 6,相当于:o.foo = foo; o.foo(1, 2, 3); delete o.foo;
    foo.apply(o, [4, 5, 6]);    // 输出:123 4 5 6,同上

    call() 与 apply() 的作用相同,区别在于接受参数的方式不同。

    构造函数

    请参考:“JavaScript快速入门笔记(7):对象” 中 “构造函数” 一节(https://www.cnblogs.com/itwhite/p/12230148.html) 

    完。

  • 相关阅读:
    C#中的global::system***命名空间别名限定符
    返回一个整数数组中最大子数组的和
    敏捷开发概述
    单词查找排序输出
    关于电梯调度的设计
    关于电梯调度的一些想法
    C#中抽象类和接口的区别
    SharePoint2010列表表单:用后台代码生成表单
    外刊IT评论:远离.net
    程序员:编程给你现实生活带来了哪些坏习惯
  • 原文地址:https://www.cnblogs.com/itwhite/p/12218038.html
Copyright © 2011-2022 走看看