JavaScript学习笔记(二) 函数

简介: JavaScript学习笔记(二) 函数

在 JavaScript 中函数是一种特殊的对象类型


1、函数定义


(1)认识函数字面量


函数字面量是定义函数的最简单、最直接的方式,它一般包含四个部分:


  • 关键字 function
  • 函数名称:函数名称用于标识函数,但是它也可以省略
  • 包含在圆括号中的一组参数:参数定义为函数中的变量,在函数调用时初始化为实际提供的值
  • 包含在花括号中的一组语句:语句是函数的主体,它们在函数被调用时执行


(2)定义函数


应用函数字面量,在 JavaScript 中提供两种方式定义函数:

  • 函数声明语句:函数声明语句是函数字面量的简单应用,实际上也是我们定义函数比较常用的方式
// 定义一个计算两数相加的函数
function add(a, b) {
    return a + b
}
// 定义一个计算阶乘的递归函数
function factorial(x) {
    return (x <= 1) ? 1 : x * factorial(x - 1)
}


  • 函数定义表达式:在 JavaScript 中,函数也是一个对象,所以我们可以把函数的定义赋值给一个变量
// 定义一个计算两数相加的函数,为了使得代码结构更加紧凑,这里的函数字面量一般省略函数名称
var add = function(a, b) {
    return a + b
}
// 定义一个计算阶乘的递归函数,为了方便函数调用自身,这里的函数字面量需要加上函数名称
var factorial = function fact(x) {
    return (x <= 1) ? 1 : x * fact(x - 1)
}


(3)对比两种定义函数的方式


两种定义函数的方式(函数声明语句和函数定义表达式)有什么不同呢?


  • 声明时机
    函数声明语句只能出现在全局代码或内嵌在其它函数中,不能出现在条件判断等语句中
    而函数定义表达式可以出现在代码中的任意地方


  • 调用时机
    以函数声明语句定义的函数,在编译时被提前到函数作用域的顶部,所以它可以在定义之前被调用
    对于函数定义表达式,虽然变量的声明会提前,但是变量的赋值不会提前,所以只能在函数定义后才能调用


2、函数调用


(1)隐式参数


在函数调用时,除了显式传入函数的实参,每个函数还会接受两个隐式参数:this 和 arguments


参数 this 的值取决于函数的调用模式;而参数 arguments 可以用于获取传入函数的所有实参


(2)函数调用方式与 this 取值


调用 JavaScript 函数常见的有三种方式,分别是函数调用、方法调用以及构造函数调用


  • 作为函数调用

最简单的一种情况,函数作为一个普通函数被调用,此时 this 被绑定到全局对象

> // 定义一个普通函数
> var add = function(a, b) {
    // 此时 this 被绑定到全局对象(在这里可以输出 this 观察一下)
    // this 的取值可能根据 JavaScript 运行环境的不同而不同
    return a + b
}
> // add 函数作为函数被调用,this 被绑定到全局对象
> // 函数调用方式:function(argument, ...)
> add(1, 1)


实际上,在函数作为普通函数被调用时,this 被绑定到全局对象是一个不太合理的设计

在《JavaScript语言精髓》一书中甚至称其为 “语言设计上的一个错误”,因为这样子容易造成全局对象的污染


  • 作为方法调用

当函数作为对象的一个属性存在时,它被称为方法,此时 this 被绑定到该对象

> // 定义一个 counter 对象
> var counter = {
    value: 0,
    // 定义 increment 函数作为方法(counter 对象的一个属性)
    increment: function() {
        // 当 increment 函数作为方法被调用时,会自动得到一个隐式参数 this,指向对象本身
        this.value += 1
    }
}
> // increment 函数作为方法被调用,this 绑定到 counter 对象
> // 方法调用方式:object.function(argument, ...)
> counter.increment()
> counter.value
// 1


  • 作为构造函数调用

构造函数的定义方法和普通函数完全一致,只是在命名上约定构造函数以大写字母开头

此时 this 被绑定到构造函数返回的新对象上

// 定义 Message 函数作为构造函数
> var Message = function(descrition) {
    // 当 Message 函数作为构造函数被调用时,会自动得到一个隐式参数 this,绑定到新对象
    this.detail = descrition
}
> // Message 函数作为构造函数被调用,this 绑定到 message 对象
> // 构造函数调用方式:new Function(argument, ...)
> var message = new Message('Hello')
> message.detail
// 'Hello'


这里存在一个严重的问题,如果说我们不小心把构造函数当成普通函数调用,想想会发生什么

此时 this 会绑定到全局对象,也就是说我们给新对象添加的属性都会添加到全局对象,造成全局对象的污染

所以我们不得不要做额外的工作来保证构造函数被正常调用

> var Message = function(descrition) {
    // 先判断 this 是否指向当前对象
    // 如果是,则说明函数是通过构造函数的方式调用的,这时可以安心进行初始化对象的工作
    if (this instanceof Message) {
        this.detail = descrition
    }
    // 如果不是,那就说明函数可能是通过错误的方式调用的,需要以正确的方式重新调用构造函数
    else {
        return new Message(descrition)
    }
}


(3)函数参数与 arguments


在 JavaScript 中,没有要求传入的实参个数与函数定义时指定的形参个数一致,这样会出现一些有趣的现象

  • 当实参个数小于形参个数

如果实参个数小于形参个数,多余的形参将会被设置为 undefined

这时,可以给传入函数的参数设置一个合适的默认值,以防止程序出现意想不到的错误

> function add(a ,b) {
    a = a || 0
    b = b || 0
    return a + b
}
> add(5, 7)
// 12
> add(9)
// 9
> add()
// 0


  • 当实参个数大于形参个数

如果实参个数大于形参个数,多余的实参也会正常传入函数,只是无法获取它们的引用罢了

这时,可以用隐式传入的参数 arguments 获取传入函数的所有实参

> function add() {
    var total = 0
    for (let curr = 0, len = arguments.length; curr < len; curr++) {
    total += arguments[curr]
    }
    return total
}
> add(1, 2, 3, 4, 5)
// 15



目录
相关文章
|
1月前
|
JavaScript 前端开发
JavaWeb JavaScript ③ JS的流程控制和函数
通过本文的详细介绍,您可以深入理解JavaScript的流程控制和函数的使用,进而编写出高效、可维护的代码。
74 32
|
4月前
|
前端开发 JavaScript 开发者
除了 Generator 函数,还有哪些 JavaScript 异步编程解决方案?
【10月更文挑战第30天】开发者可以根据具体的项目情况选择合适的方式来处理异步操作,以实现高效、可读和易于维护的代码。
|
4月前
|
JavaScript 前端开发 Java
[JS]同事:这次就算了,下班回去赶紧补补内置函数,再犯肯定被主管骂
本文介绍了JavaScript中常用的函数和方法,包括通用函数、Global对象函数以及数组相关函数。详细列出了每个函数的参数、返回值及使用说明,并提供了示例代码。文章强调了函数的学习应结合源码和实践,适合JavaScript初学者和进阶开发者参考。
62 2
[JS]同事:这次就算了,下班回去赶紧补补内置函数,再犯肯定被主管骂
|
5月前
|
JavaScript 前端开发
JavaScript 函数语法
JavaScript 函数是使用 `function` 关键词定义的代码块,可在调用时执行特定任务。函数可以无参或带参,参数用于传递值并在函数内部使用。函数调用可在事件触发时进行,如用户点击按钮。JavaScript 对大小写敏感,函数名和关键词必须严格匹配。示例中展示了如何通过不同参数调用函数以生成不同的输出。
|
5月前
|
存储 JavaScript 前端开发
JS函数提升 变量提升
【10月更文挑战第6天】函数提升和变量提升是 JavaScript 语言的重要特性,但它们也可能带来一些困惑和潜在的问题。通过深入理解和掌握它们的原理和表现,开发者可以更好地编写和维护 JavaScript 代码,避免因不了解这些机制而导致的错误和不一致。同时,不断提高对执行上下文等相关概念的认识,将有助于提升对 JavaScript 语言的整体理解和运用能力。
|
5月前
|
存储 JavaScript 前端开发
JavaScript数据类型全解:编写通用函数,精准判断各种数据类型
JavaScript数据类型全解:编写通用函数,精准判断各种数据类型
99 0
|
5月前
|
存储 JavaScript 前端开发
js中函数、方法、对象的区别
js中函数、方法、对象的区别
59 2
|
5月前
|
JavaScript 前端开发
js教程——函数
js教程——函数
76 4
|
5月前
|
JavaScript 前端开发
Node.js 函数
10月更文挑战第5天
39 3
|
5月前
|
JavaScript 前端开发 Java
【javaScript数组,函数】的基础知识点
【javaScript数组,函数】的基础知识点
52 5

热门文章

最新文章