JavaScript语言精粹学习笔记之函数(一)

Javascript的简单类型包括

1.数字number

        JS不分整型与浮点型

        两个浮点数相加,精度不够

2.字符串 string

3.布尔值 boolean

4.null

5.undefined

一、函数对象

      函数(Function)包含一组语句,它们是JavaScript的基础模块单元,用于代码复用、信息隐藏和组合调用。JavaScript中的函数就是对象。对象是“name/value”的集合并拥有一个连到原型对象的隐藏连接。对象字面量产生的对象连接到Object.prototype。函数对象连接到Function.prototype(该原型对象本身连接到Object.prototype)。每个函数在创建的时候会附加两个隐藏属性:函数的上下文和实现函数行为的代码。 
      每个函数对象在创建时也有一个prototype属性。它的值是一个拥有constructor属性且值就是该函数的对象。这和隐藏连接到Function.prototype完全不同。这个构造过程的意义详见下一章的学习笔记。 
      因为函数是对象,所以它们可以像其他任何值一样被使用。函数可以保存在变量、数组和对象中。函数可以被当做参数传递给其他函数,函数也可以返回函数。同时,由于函数是对象,所以函数可以拥有方法。 
     

二、函数字面量

        函数字面量定义了函数值,它可以有一个可选的值,用于递归地调用自己。也可以指定一个参数列表,这些参数将作为变量由调用时传递的实际参数(arguments)初始化。函数的主题包括变量定义和语句。

        函数字面量可以出现在任何允许表达式出现的地方。函数也可以被定义在其他函数中,一个内部函数可以访问自己的参数和变量,同时也能方便的访问它被嵌套在其中的那个函数的参数与变量。通过函数字面量创建的函数对象包含一个连到外部上下文的连接。这被称为闭包。它是JavaScript强大表现力的根基。

三、函数的调用

        函数与众不同之处就在于它们可以被调用。

        调用一个函数回暂停当前函数的执行,并传递控制权和参数给新函数。除了声明时定义的形式参数,每个函数还会接受两个附加的参数:this 和 arguments。 
      参数this在面向对象编程中十分重要,它的值取决于调用的模式。JavaScript一共有4种调用模式:方法调用模式、函数调用模式、构造器调用模式和apply调用模式。这些模式在如何初始化this参数上有所差异。 
      当实际参数(arguments)的个数与形式参数(parameters)的个数不匹配时,不会导致运行时错误。实际参数的个数大于形式参数的个数时,多余的实际参数会被忽略;而实际参数的个数小于形式参数的个数时,缺少的会被替换为undefined。而对于参数值,不会进行类型检查,任何类型的值都可以被传给参数。

 方法调用模式

        当一个函数被保存为对象的一个属性时,我们称它为一个方法。当一个方法被调用时,this

被绑定到改对象。如果一个调用表达式包含一个属性存取表达式,那么它被当做一个方法来调用。

// 创建 myObject. 它有一个 value 属性和一个 increment 方法。
// increment 方法接受一个可选的参数。如果参数不是数字,那么默认使用数字1.

var myObject = {
    value: 0;
    increment: function (inc) {
        this.value += typeof inc === 'number' ? inc : 1 ;
    }
};

myObject.increment () ;
document.writeln(myObject.value);  // 1

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

方法可以使用 this 去访问对象,所以它能从对象中取值或修改该对象。

通过 this 可取得它们所属对象的上下文的方法称为公共方法。

函数调用模式

        当一个函数并非一个对象的属性时,那么它被当做一个函数来调用:

var sum = add(3, 4);  // sum 的值为7

        当函数以此模式调用时,this 被绑定到全局对象。这是语言设计上的错误。因为内部函数的 this 被绑定了错误的值,所以不能共享方法对对象的访问权。我们有一个很容易的解决方案:

如果该方法定义一个变量并给它赋值为 this ,那么内部函数就可以通过那个变量访问到 this。

// 给 myObject 增加一个 double 方法。

myObject.double = function () {
    var that = this; // 解决方法
    
    var helper = function () {
        that.value = add(that.value, that.value);
    };
    
    helper(); // 以函数的形式调用 helper.
};

// 以方法的形式调用 double.

myObject.double();
document.writeln(myObject.getValue()); // 6

构造器调用模式

        JavaScript 是一门基于原型继承的语言,这意味着对象可以直接从其他对象继承属性。

如果在一个函数前面带上 new 来调用, 那么将创建一个隐藏连接到该函数的 prototype 成员的新对象,同时 this 将会绑定到那个新对象上。

new 前缀也会改变 return 语句的行为。

// 创建一个名为 Quo 的构造器函数。它构造一个带有 status 属性的对象。

var Quo = function (string) {
    this.status = string;
};

// 给 Quo 的所有实例提供一个名为 get_status 的公共方法。

Quo.prototype.get_status = funcrion () {
    return this.status;
};

// 构造一个 Quo 实例

var myQuo = new Quo("confused");

document.writeln(myQuo.get_status());

目的是结合 new 前缀调用的函数被称为构造器函数。它们保存在以大写格式命名的变量里。如果调用构造器函数时没有在前面加上 new ,可能会发生非常糟糕的事情,既没有编译时警告,也没有运行时警告,所以大写约定非常重要。

Apply 调用模式

        apply 方法让我们构建一个参数数组并用它去调用函数。它允许我们选择 this 的值。

apply 方法接收两个参数。第一是将被绑定给 this 的值。第二个是一个参数数组。

// 构造一个包含两个数字的数组, 并将它们相加。
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'

四、参数

        当函数被调用时,会得到一个参数,那就是 arguments 数组。通过它,函数可以访问所有它被调用时传递给它的参数列表,包括那些没有被分配给函数声明时定义的形式参数的多余参数。这

使得编写一个无须指定参数个数的函数成为可能:

// 构造一个将很多个值相加的函数

// 注意改函数内部定义的变量 sum 不会与函数外部定义的 sum 产生冲突。
// 该函数只会看到内部的那个变量。

var sum = function () {
    var i, sum = 0;
    for (i = 0; i < arguments.length; i += 1) {
        sum += arguments[i];
    }
    return sum;
};

document.writeln(sum(4, 8, 15, 16, 23, 42)); // 108

五、返回

        当一个函数被调用时,它从第一个语句开始执行,并在遇到关闭函数体的 } 时结束。使得函数把控制权交还给调用该函数的程序部分。

return 语句可以用来使函数提前返回。当 return 被执行时,函数立即返回而不再执行其余的语句。

一个函数总是会返回一个值,如果没有指定返回值,则返回 undefined.

如果函数以在前面加上 new 前缀的方式来调用,且返回值不是一个对象,则返回 this 

六、异常

        JS提供了一套异常处理机制。异常是干扰程序的正常流程的非正常的事故。当查出这样的事故时,你的程序应该抛出一个异常:

var add = function (a, b) {
    if (typeof a !== 'number' || typeof b !== 'number') {
        throw {
            name: 'TypeError',
            message: 'add needs numbers'
        };
    }
    return a + b;
}

throw 语句中断函数的执行,它应该抛出一个exception 对象,该对象包含可识别异常类型的 name

属性和一个描述性的 message 属性。你也可以添加其他属性。

该 exception 对象将被传递到一个 try 语句的 carch 语句:

// 构造一个 try_it 函数, 用不正确的方式调用之前的 add 函数

var try_it = function () {
    try {
        add("seven");
    } catch (e) {
        document.writeln(e.name + ': ' + e.message);
    }
}

Try_it();

如果在 try 代码块内抛出异常,控制权就会跳转到它的 carch 从句。

一个try 语句只会有一个将捕获所以异常的 catch 代码块。如果你的处理手段取决于异常的类型,那么异常处理器必须检查异常对象的name 属性以确定异常的类型。

七、给类型增加方法

        JS 允许给语言的基本类型增加方法。如,通过给 Object.prorotype 添加方法来使用该方法对所有对象可用。这样的方式对函数、数组、字符串、数字、正则表达式和布尔值同样适用。

我们可以通过给 Function.prototype 增加方法来使得该方法对所有函数可用:

Function.prototype.method = function (name, func) {
    this.prototype[name] = func;
    return this;
};

通过给 Function.prototype 增加一个 method 方法,我们就不必键入 prototype 这个属性名。这个缺点就被掩盖了。

JS没有单独的整数类型, 我们可以通过给 Number.prototype 添加一个 integer 方法来改善它。它会根据数字的正负来判断是使用 Math.ceiling 还是 Math.floor.

Number.method('integer', function () {
    return Math[this < 0 ? 'ceiling' : 'floor'](this);
});

document.writeln((-10 / 3).integer());  // -3

通过给基本类型增加方法,我们可以大大提高语言的表现力。

基本类型的原型是公共的结构,所以在类库混用时要小心,保险的做法就是在确定没有该方法时才去添加它。

// 有条件地增加一个方法

Function.portotype.method = function (name, func) {
    if (!this.portotype[name]) {
        this.prototype[name] = func;
    }
};

同时还要注意 for in 语句用在原型上时表现是很糟糕的,我们可以使用 hasOwnProperty 方法去筛选出继承而来的属性,或者我们可以查找特定的属性。

八、递归

        递归函数会直接调用自身的一种函数。

        递归函数可以非常高效地操作树形结构,比如浏览器端的文档对象模型(DOM).每次递归调用时处理给定树的一小段。

// 定义 walk_the_DOM 函数,它从某个给定节点开始,接 HTML 源码中的顺序访问该树的每个节点。
// 它会调用一个函数,并依次传递每个节点给它。 walk_the_DOM 调用自身去处理每个子节点

var walk_the_DOM = function walk (node, func) {
    func(node);
    node = node.firstChild;
    while (node) {
        walk(node, func);
        node = node.nextSibling;
    }
};

尾递归:是一种在函数的最后执行递归调用语句的特殊形式的递归。

var factorial = function factorial(i, a) {
    a = a || 1;
    if (i < 2) {
        return a;
    }
    return factorial(i - 1, a * i);
}

以下链接是JS语言精粹学习笔记之 函数 第二篇,欢迎共同探索讨论。

https://blog.csdn.net/ljx15970777407/article/details/118708080

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值