JS【详解】函数 (声明函数、调用函数、函数表达式、匿名函数、立即执行函数、箭头函数、内置函数、回调函数、私有函数、高阶函数、模拟函数重载)

函数用于封装一段具有特定功能代码,通过调用的形式执行。

  • 每个函数都有返回值,无 return 语句时返回 undefined

声明函数

  • 在浏览器中,在最外层声明的函数,都是 Window 对象的方法
  • 函数的声明会被提前:可以在函数声明之前,调用函数,因为声明的函数会在所有代码执行之前被创建。(与变量提升相同)
function sum(a, b) {return a + b;
}
  • 关键字 function
  • 函数名 sum (命名规则与变量名相同,通常以动词开头)
  • 形式参数 a 和 b ,用 , 分隔
    • 形式参数即形式上传递的参数,因为它们只是函数调用时,传入的实际参数的替身
    • 声明形参相当于在函数内部声明了对应的变量,但是并不赋值
    • 形参的长度可通过 函数名.length 获取
  • 返回值 a + b 的计算结果

函数的参数根据功能需要定义,也可以没有参数

function sayHi(){alert('Hi')
}

如果函数的参数超过 3 个,则建议将它们以对象的形式传入,好处如下:

  • 不用考虑参数的顺序
  • 更易扩展
let params = {a: 1,b: 2,c: 3,d: 4,
};function sum(params) {return params.a + params.b + params.c + params.d;
}

用解构赋值的写法更简洁

function sum({ a, b, c, d }) {return a + b + c + d;
}

给函数添加注释

/*** 功能:给定元素查找他的第一个元素子节点,并返回* @param 参数 ele -- DOM 元素* @returns 返回值 node -- DOM节点*/
function getFirstNode(ele){let node = ele.firstElementChild || ele.firstChild;return node;
}

指定形式参数的默认值

// 给形式参数 b 指定了默认值 1
function sum(a, b = 1) {return a + b;
}
  • 指定默认值的参数,要放在无默认值参数的后面

  • 调用函数时,若传入了对应的实际参数,则使用实际参数,若没有传入实际参数,则使用形式参数的默认值

  • 参数的默认值可以是包含其他参数的表达式

    function sum(a = 1, b = a + 1) {return a + b;
    }
    
  • 默认参数有独立的作用域,介于函数外作用域和函数内作用域之间。

    let x = 1;
    function fn(x, y = x) {// 在参数作用域内,在函数调用时,传入的实际参数将 x 赋值为 2,和外部的 x 无关console.log(x, y);
    }
    fn(2); // 打印 2 2
    
    let x = 1;
    function fn(z, y = x) {// 在参数作用域内,未找到 x 的定义,只能从外层找到 x = 1console.log(z, y);
    }
    fn(2); // 打印 2 1
    

剩余参数 …

ES6 新增语法

用于便捷获取和使用调用函数时传入的超出声明时形式参数数量的实际参数。

function demo(a, ...moreParams) {console.log(moreParams); // 打印数组 ["2","3"]
}
demo("1", "2", "3");
  • ... 为前缀的形式参数即剩余参数
  • 剩余参数必须写在所有形式参数的末尾( 所以每个函数也只能声明一个剩余参数 )
  • 剩余参数的类型是数组,可使用所有的数组 API 来处理剩余参数。

构造函数

用于创建对象

  • 声明方式与普通函数类似,函数名通常为一个名词,且首字母大写
  • 构造函数中的 this 指向新创建的对象
// 构造函数 Person
function Person(name) {this.name = name;
}// 通过构造函数 Person 创建对象 
new Person("朝阳")

new 运算符创建对象的过程

  1. 在堆内存中开辟空间,存储新创建的对象
  2. 将新创建的对象赋值给构造函数中的 this
  3. 执行构造函数中的代码(主要是设置对象的属性和方法)
  4. 将新创建的对象作为返回值返回

调用函数

调用函数,即触发函数内代码的执行!

函数名后加 () ,并在() 内根据函数的声明,传入必要的参数,就能调用函数。

  • 调用函数时,除了传入形式参数列表中列出的参数外,还有两个隐含参数(未在形式参数列表中列出,也未在函数内声明,但可以直接在函数内使用的变量)this 和 arguments (下文有详解)
function sum(a, b) {return a + b;
}// 调用函数,传入实际参数 1 和 2
let result = sum(1, 2);console.log(result); // 打印 3

调用函数时传入的实际参数的顺序,与函数声明时形式参数的顺序一一对应!

上例中,实际参数 1 会作为形式参数 a 的值传入函数,实际参数 2 会作为形式参数 b 的值传入函数,即在此次函数调用过程中,a 的值为1,b 的值为 2。

之后再次调用函数时,又可以传入其他参数,如

sum(4,5) // 返回结果 9

此次函数调用过程中,a 的值为4,b 的值为 5。

所以函数就像一个破壁机一样,随传入参数的不同,得到的结果也不同,但执行的功能没有变化。(破壁机执行的功能是搅碎并混合均匀,投入黄豆和水得到豆浆,投入西瓜得到西瓜汁)

隐含参数 this

https://blog.csdn.net/weixin_41192489/article/details/123093256

浏览器中,最外层的 普通函数 的 this 是 window 对象

function Person(name) {console.log(this); // 浏览器中,控制台打印  window 对象this.name = name;
}
Person("朝阳");console.log(window.name); // 浏览器中,控制台打印  "朝阳"

可以这样理解:浏览器中,最外层的 普通函数 声明之后,其实是window 对象的方法,在 window 对象的方法内,this 自然指向 window 对象

此范例中的函数,若作为构造函数创建对象,则 this 将指向新对象

function Person(name) {// 作为构造函数创建新对象时,this 指向新对象console.log(this); // 控制台打印  Person 对象this.name = name;
}let me = new Person("朝阳");
console.log(me.name); // 控制台打印  "朝阳"

隐含参数 arguments

  • 调用函数时,传递的所有实参(实际传递的参数)都存在 arguments中。
  • arguments 是一个对象,严格讲是类数组,不是真正的数组,很多特性和数组很像,比如包含了索引元素和 length属性,但不支持 sort()、slice() 等数组方法。
  • 不定义形参,也可以通过arguments 来使用实参(只不过比较麻烦):arguments[0] 表示第一个实参、arguments[1] 表示第二个实参…
// 函数--任意数量参数的求和
function sum() {var sum = 0;for(var i = 0; i < arguments.length; i++){sum += arguments[i];}return sum;
}

将类数组 arguments 转换数组

function f(){var args = [].slice.call(arguments);return args.reverse();
}f(1,2,3,4); // 得到 [4,3,2,1]

函数表达式

函数的声明本身就是一个表达式,即函数声明表达式,所以可以赋值给一个变量。

let sum_func = function sum(a, b) {return a + b;
};

此时,变量 sum_func 内存储的是函数在堆内存中的地址。

这种方式创建的函数的函数名已无任何作用(无法用于调用函数),所以通常无需定义函数名

let sum_func = function (a, b) {return a + b;
};

匿名函数

没有函数名的函数,即匿名函数,通常在函数表达式和立即执行函数中使用。

立即执行函数

声明函数后,立即被调用执行的函数即立即执行函数(又名即时函数)

(function (a, b) {console.log(a + b);
})(1, 2); // 控制台打印 3

箭头函数 =>

ES6 新增语法

  • 简化了匿名函数的写法
  • 箭头函数中的 this 继承外层的 this (使用 call , bind , apply 都无法改变 this 的指向)
// 无参数
let a = () => {console.log(1);
};// 一个参数
let b = (i) => {console.log(i);
};// 多个参数
let c = (i, j) => {return i + j;
};

若函数内仅 return 语句,则可省略 { retrun },简写为

let c = (i, j) => i + j;

内置函数

内置函数即 JavaScript 默认已封装好的全局函数,都可以当作 window 对象的方法来调用

延时调用定时器 setTimeout ()

https://blog.csdn.net/weixin_41192489/article/details/139287319

循环调用定时器 setInterval()

  • 参数1:回调函数,该函数会每隔一段时间被调用一次。
  • 参数2:每次调用的间隔时间,单位是毫秒。
let num = 1;
setInterval(function () {// 每间隔一秒,数字加1num ++;console.log(num);
}, 1000);

返回一个Number类型的数字,它是定时器的唯一标识,可用于清除定时器。

    let num = 1;const timer = setInterval(function () {num ++;if(num === 5) {// 清除定时器clearInterval(timer);}}, 1000);

编码 encodeURI()

url 中的一些特殊字符(如空格)需要通过 encodeURI 编码后才方便使用。

let url = 'http:**?q=this and that';
// 将空格转换为了 %20
encodeURI(url); // 得到 "http:**?q=this%20and%20that"

反编码 decodeURI()

将被 encodeURI 编码的字符串恢复原样。

// %20 变回空格
decodeURI("http:**?q=this%20and%20that") // 得到 'http:**?q=this and that'

回调函数 callback

若函数 A 会被函数 B 在未来的某个合适的时间调用,则函数 A 就是函数 B 的回调函数,通常被作为函数的参数传入函数内。

function A (value) {alert(value);
}
function B (someFunction, value) {someFunction(value);
}// 此时的函数 A 就是函数 B 的回调函数
B(A, 'hi');

回调函数也可以是一个匿名函数,比如 setTimeout 和 setInterval 的第一个参数。

setTimeout(function () {console.log('1秒后,执行setTimeout的回调函数');
},10000)

私有函数

在函数内声明的函数,用于限制该函数只能在函数内部被调用,也有利于减少命名冲突。

function sum(a, b) {// 私有函数 addfunction add(value) {return ++value;}return a + add(b);
}let result = sum(1, 2); // 结果为 4// 报错 add is not defined
add(6);

高阶函数

将函数作为参数的函数称为高阶函数,如 setTimeout 和 setInterval 等。

setTimeout(function () {console.log('1秒后,执行setTimeout的回调函数');
},10000)

模拟函数重载

函数重载:定义几个函数名相同,但参数个数或类型不同的函数,在调用时传入不同的参数,编译器会自动调用适合的函数。

在JavaScript中,同一个作用域,出现两个名字一样的函数,后面的会覆盖前面的,所以 JavaScript 没有真正意义的重载,但可以模拟实现:

function overload () {if (arguments.length === 1) {console.log('一个参数')}if (arguments.length === 2) {console.log('两个参数')}
}overload(1);      //一个参数
overload(1, 2);  //两个参数

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/872383.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

QThread和std::thread

在 Qt 中&#xff0c; 我们经常会用到多线程&#xff0c;这时候就需要纠结是使用 Qt 的 QThread 还是使用 C 标准库的 std::thread。 这里记录一下我自己的理解&#xff0c;先介绍一下 QThread 和 std::thread 的使用方法&#xff0c;对比一下他们的不同&#xff0c;最后说一下…

【Redis】集群

文章目录 一、集群是什么&#xff1f;二、 Redis集群分布式存储为什么redis集群的最大槽数是16384&#xff08;不太懂&#xff09;redis的集群主节点数量基本不可能超过1000个 三、 配置集群&#xff08;三主三从&#xff09;3.1 配置config文件3.2 启动六台redis3.2 通过redis…

理兔chat开发日记

1.注册 注册跟以前的差不多&#xff0c;我们将我们的验证码放在redis下&#xff0c;我们在注册的时候先判断我们输入的验证码是否正确 验证码成功后在我们的实现类中&#xff0c;我们先判断邮箱是否重复&#xff0c;不重复我们就继续注册 我们拥有联号注册的功能&#xff0c;就…

unity局部坐标和世界坐标角度介绍

在Unity中&#xff0c;局部坐标&#xff08;Local Coordinates&#xff09;和世界坐标&#xff08;World Coordinates&#xff09;是描述物体位置的两种不同方式&#xff1a; 局部坐标&#xff08;Local Coordinates&#xff09;&#xff1a; 局部坐标是相对于物体自身的坐标系…

Puppeteer 是什么以及如何在网络抓取中使用它 | 2024 完整指南

网页抓取已经成为任何处理网页数据提取的人都必须掌握的一项重要技能。无论你是开发者、数据科学家还是希望从网站收集信息的爱好者&#xff0c;Puppeteer都是你可以使用的最强大工具之一。本完整指南将深入探讨什么是Puppeteer以及如何有效地在网页抓取中使用它。 Puppeteer简…

日志的编写与线程池的结合

目录 一、认识日志 二、时间的等级划分 三、日志的输出端 3.1 保存至文件 四、日志的部分信息 4.1 日志等级 4.2 日志时间 五、加载日志 六、日志的宏编写 七、ThreadPool Log 一、认识日志 记录事件&#xff1a; 日志用于记录系统运行过程中发生的各种事件&…

Linux硬件中断(IRQ)的基础知识

目录 一、中断的概念1.1 什么是硬件中断1.2 中断类型二、中断处理的工作原理2.1 中断请求2.2 中断向量2.3 中断服务例程(ISR)2.4 上下文切换2.5 中断处理2.6 任务恢复三、中断处理的编程3.1 注册中断处理函数3.2 注销中断处理函数四、中断和系统性能4.1 中断风暴4.2 IRQ亲和性…

创作模板四【创作模板】

xxx【创作模板四】 前言推荐说明最后 前言 2023年7月7日 以下内容源自《【创作模板四】》 仅供学习交流使用 推荐 无 说明 大三下期末考试进行中 【最后】的文案&#xff1a; 当时期末复习总结的文章&#xff0c;很少有人点赞 确实是很失望&#xff0c;只能自娱自乐&…

数据库SQL Server时间函数Datetime

文章目录 SQL Server 提供了一系列用于处理日期和时间的函数&#xff0c;以下是一些常用的时间函数&#xff1a; GETDATE()&#xff1a;返回当前的日期和时间。 SELECT GETDATE();CURRENT_TIMESTAMP&#xff1a;与 GETDATE() 类似&#xff0c;返回当前的日期和时间。 SELECT…

CloudCone服务器2核1G一年只需15刀

CloudCone服务器博主本人已稳定使用一年多了&#xff0c;非常划算且稳定。2核1G一年才15&#xff0c;相比其他厂家2核动辄月付10左右的价格&#xff0c;cloudcone简直没有对手。 但是15刀这些划算的内容无法在官网直接找到。 博主这里记录 cloudcone.top 这个url&#xff0c;…

Linux Vim编辑器全攻略:从入门到精通

引言 简要介绍Vim编辑器的历史、地位及其在Linux及Unix系统中的广泛应用。强调Vim作为程序员和系统管理员的首选工具之一&#xff0c;其强大的文本编辑能力和高效的编辑模式。 Vim基础篇 安装Vim 介绍在不同Linux发行版上安装Vim的方法&#xff08;如使用apt-get、yum、dnf等…

elementui 日历组件el-calendar使用总结

功能&#xff1a; 1.日历可以周视图、月视图切换&#xff1b; 2.点击月视图中日期可以切换到对应周视图&#xff1b; 3.点击周视图查看当日对应数据&#xff1b; 4.周、月视图状态下&#xff0c;点击前后按钮&#xff0c;分别切换对应上下的周、月&#xff1b; 5.点击回到…

算法 —— 高精度(模拟)

目录 加法高精度 两个正整数相加 两个正小数相加 两正数相加 减法高精度 两个正整数相减 两个正小数相减 两正数相减 加减法总结 乘法高精度 两个正整数相乘 两个正小数相乘 乘法总结 加法高精度 题目来源洛谷&#xff1a;P1601 AB Problem&#xff08;高精&#x…

单片机外围设备-EEPROM

eeprom用iic通信。eeprom有几个特点需要关注&#xff1a; 1、可以单字节读写 2、eeprom按页划分存储&#xff0c;不同型号的eeprom的页大小不一致&#xff0c;往eeprom写数据时&#xff0c;如果写到了该页的末尾&#xff0c;会自动从该页的开头继续写&#xff0c;把之前的数据…

如何PR到别人仓库(指定分支,无废话)

如何PR到别人仓库&#xff08;指定分支&#xff09; 记录一下&#xff0c;之前都是直接master分支&#xff0c;现在记录如何pr到别人仓库的其他分支 首先进入别人仓库然后点击fork到自己仓库 步骤&#xff08;以博主自己一个例子为例&#xff09; &#xff08;1&#xff09;…

c++ primer plus 第16章string 类和标准模板库,16.1.3 使用字符串

c primer plus 第16章string 类和标准模板库,16.1.3 使用字符串 c primer plus 第16章string 类和标准模板库,16.1.3 使用字符串 文章目录 c primer plus 第16章string 类和标准模板库,16.1.3 使用字符串16.1.3 使用字符串程序清单16.3 hangman.cpp 16.1.3 使用字符串 现在&a…

【题目/训练】二叉树的创建遍历(递归非递归)

一、根据二叉树创建字符串 思路&#xff1a;在正常前序递归遍历的基础上&#xff0c;单独加上一个考虑到右子树为空的情况&#xff0c;如下&#xff1a;其结果为 1&#xff08;2&#xff08;4&#xff08;5&#xff09;&#xff08;6&#xff09;&#xff09;&#xff09;&…

android11为开机动画添加铃声(语音)

一、碰到的问题 1、第一次开机无铃声 2、开机时铃声和动画不同步&#xff0c;开头的铃声会丢失 3、开机时铃声/动画不能完全播放完 二、解决 以下为添加的patch /开机铃声不同步&#xff0c;语音第一段无声 diff --git a/media/libmediaplayerservice/MediaPlayerService…

馥郁珍藏:品味红酒的层次与细腻

在生活的点滴中&#xff0c;总有一些事物以其不同的魅力&#xff0c;让我们为之驻足&#xff0c;为之沉醉。红酒&#xff0c;便是其中之一。它不仅仅是一种饮品&#xff0c;更是一种情感的寄托&#xff0c;一种生活的艺术。今天&#xff0c;就让我们一起走进红酒的世界&#xf…

原码补码反码移码

符号位为左边的第一位&#xff0c;正数的为0 &#xff0c;负数为1&#xff1b; 正数 原码、反码、补码一致&#xff1b;移码是补码符号位取反。 负数的反码为 符号位不变以原码其他位 取反&#xff0c;补码是反码加1位&#xff0c;移码是补码的符号位取反&#xff1b;