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) 

完。

原文地址:https://www.cnblogs.com/itwhite/p/12218038.html