《JavaScript语言精粹》读书笔记- 函数

《JavaScript 语言精粹》(修订版) 读书笔记

第四章 函数 Functions


函数字面量

函数字面量包含4个部分:

  • 第一部分, 保留字 function
  • 第二部分, 函数名,它可以被忽略。没有函数名,则被称为匿名函数
    好处:
    • 可以通过函数名,递归的调用自己。
    • 此名字也可以被调试器和开发工具用来识别函数。
  • 第三部分, 包围在圆括号中的一组参数。这些参数的名称将被定义为函数中的变量。它们不像普通的变量那样将被初始化为undefined,而是在函数被调用时初始化为实际提供的参数的值。
  • 第四部分, 包围在花括号中的一组语句。也是函数的主体,它们在函数被调用时执行

通过函数字面量创建的函数对象包含一个连接到外部上下文的连接。这被称为闭包(closure),它是JavaScript强大表现力的来源。


调用 Invocation

调用一个函数会暂停当前函数的执行,传递控制权和参数给新函数,除了声明时定义的形式参数,每个函数还连接两个附加的参数:this 和 arguments
this 的值取决于调用的模式
在JavaScript中一共有4中调用模式:

  • 方法调用模式
  • 函数调用模式
  • 构造器调用模式
  • apply调用模式

调用运算符:跟在任何产生一个函数值的表达式之后的一对圆括号()。表达式内可包含零个或多个用逗号隔开的表达式。 每个表达式产生一个参数值,es6语法中可以设置默认参数。如果实际参数值过多,超出的参数值会被忽略。过少,缺失的值会被替换为undefined。任何类型的值都可以被传递给任何参数。

  • 方法调用模式 The Method Invocation Pattern

    当一个函数被保存为对象的一个属性时,我吗称它为一个方法。方法被调用时,this被绑定在该对象。如果调用表达式包含一个提取属性的动作(.点表达式或者[subscript]下标表达式),那么它就是被当做一个方法来调用。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var myObject = {
    value:0,
    increment:function(inc) {
    this.value += typeof inc === "number"?inc:1;
    }
    };
    myObject.increment();
    document.write(myObject.value); // 1

    myObject.increment(2);
    document.write(myObject.value); //3

    this 到对象的绑定发生在调用的时候。这个“超级”延迟绑定(very late binding)使得函数对this高度复用。
    通过this可获取它们所属对象的上下文的方法称为公共方法(public method)

  • 函数调用模式 The Function Invocation Pattern

    当一个函数并非一个对象的属性时,那么它就是被当做一个函数来调用:
    var sum = add(3,4)
    this 被绑定到了全局对象上了。倘若语言设计正确,那么当内部函数被调用时,this应该仍然绑定外部函数的this变量。通常定义一个 that变量,并给它赋值为this

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    muyObject.double = function(){
    var that = this; // 解决方法
    var helper = function(){
    that.value = add(that.value,that.value);
    }
    helper(); // 以函数的形式调用helper
    }
    // 以方法的形式调用double 。
    myObject.double();
    document.writeln(myObject.value) // 6;
  • 构造器调用模式

    一个函数,如果创建的目的就是希望结合new的前缀来调用,那它就被称为构造器构造

    按照约定,它们保存在以大写格式命名的变量里

    JavaScript 是一门基于原型继承的语言。这意味着对象可以直接从其他对象继承属性,同时,他也提供了一套和基于类的语言类似的对象构建语法。
    如果在一个函数前面带上 new 来调用。那么背地里将会创建一个连接到该函数的 prototype成员的新对象,同时 this 会被绑定到那个新对象上。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // 创建一个名为Quo的构造器函数,它构造一个带有status属性的对象
    var Quo = function(string) {
    this.status = string;
    }

    // 给Quo的所有实例提供一个名为get_status的公共方法
    Quo.prototype.get_status = function() {
    return this.status
    }

    // 构造一个Quo 实例
    var myQuo = new Quo("confused")

    document.writeln(myQuo.get_status()); // 显示 "confused"
  • Apply调用模式

    JavaScript 是一门函数式的面向对象编程语言,所以函数可以拥有方法。
    apply方法让我们构建一个参数数组传递给调用函数,同时允许我们选择this的值。
    接收两个参数,第一个是要绑定给this的值,第二个就是一个参数数组。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     // 构造一个包含两个数字的数组,并将它们相加。
    var array = [3,4];
    var sum = add.apply(null,array); // sum 值为7
    // 构造一个包含status 成员的对象。
    var statusObject = {
    status:"A-OK"
    };

    // statusObject 并没有继承自Quo.prototype ,
    // 但我们可以在 statusObject上调用get_status方法,尽管statusObject 并没有一个名为get_status的方法。

    var status = Quo.prototype.get_status.apply(statusObject);
    // status 值为 'A-OK'