第122篇: JS函数一些基本概念
好家伙,本篇为《JS高级程序设计》第十章“函数”学习笔记
1.函数的三种定义方式:函数表达式、函数声明及箭头函数
函数声明:
function sum(a) {
return a + 1;
}
函数表达式:
let sum= function(a){
return a + 1;
}
箭头函数:
let sum = (a) => {
return a + 1;
}
以函数声明方式声明的函数存在"函数声明提升",
在执行代码时,JavaScript 引擎会先执行一遍扫描, 把发现的函数声明提升到源代码树的顶部。
因此即使函数定义出现在调用它们的代码之后,引擎也会把 函数声明提升到顶部。
而函数表达式这么做会报错(箭头函数同样报错)

代码如果没有执行到函数表达式的那一行,那么执行上下文中就没有函数的定义
2.函数名
函数名是指向函数的指针,所以它们跟其他包含对象指针的变量具有相同的行为。
function sum(num1, num2) {
return num1 + num2;
}
console.log(sum(10, 10)); // 20
let anotherSum = sum;
console.log(anotherSum(10, 10)); // 20
sum = null;
console.log(anotherSum(10, 10)); // 20
以上代码定义了一个名为 sum()的函数,用于求两个数之和。
然后又声明了一个变量 anotherSum, 并将它的值设置为等于 sum。
注意,使用不带括号的函数名会访问函数指针,而不会执行函数。
此时, anotherSum 和 sum 都指向同一个函数。
调用 anotherSum()也可以返回结果。把 sum 设置为 null 之后,就切断了它与函数之间的关联。
而 anotherSum()还是可以照常调用,没有问题。(有意思,之前不清楚)
ECMAScript 6 的所有函数对象都会暴露一个只读的 name 属性,其中包含关于函数的信息。
多数情 况下,这个属性中保存的就是一个函数标识符,或者说是一个字符串化的变量名。
即使函数没有名称, 也会如实显示成空字符串。
function AAA(){}
let BBB =function (){}
let CCC =()=>{}
console.log(AAA.name);
console.log(BBB.name);
console.log(CCC.name);
console.log((()=>{}).name);

(最后一行有东西的,空字符)
3.参数
ECMAScript 函数的参数跟大多数其他语言不同。
ECMAScript 函数既不关心传入的参数个数,也不 关心这些参数的数据类型。
定义函数时要接收两个参数,并不意味着调用时就传两个参数。
你可以传一 个、三个,甚至一个也不传,解释器都不会报错。(好家伙)
4.没有重载
js没有重载
(这可真是太有意思了,方法名是指针,参数不管数量,我想js自然是不会有重载的)
方法后定义覆盖先定义(记住了,要考的)
function add(num) {
return num + 100;
}
function add(num) {
return num + 200;
}
let result = add(100); // 300
显然,定义两个同名参数,后定义的会覆盖先定义的
5.arguments属性
arguments 是一个类数组对象,包含调用函数时传入的所有参数。
function test(a,b,c,d,e){
console.log(arguments)
}
test(1,2,3,4);

5.1.arguments.callee
arguments 对象其实还有一个 callee 属性,是一个指向 arguments 对象所在函数的 指针。
想不出什么好的例子,就用书中的原例吧:
(书中原例)
一个阶乘递归
function factorial(num) {
if (num <= 1) {
return 1;
} else {
return num * factorial(num - 1);
}
}
随后用arguments.callee代替factorial
function factorial(num) {
if (num <= 1) {
return 1;
} else {
return num * arguments.callee(num - 1);
}
}
这时候可能有人会问了,这有什么屌用.我刚开始也是这么想的,后来又看了两遍,发现js开发者还是有点东西的
使用 arguments.callee 就可以让函数逻辑与函数名解耦
我们接着看:
(重要的一个例子)
function factorial(num) {
if (num <= 1) {
return 1;
} else {
return num * arguments.callee(num - 1);
}
}
let trueFactorial = factorial;
factorial = function () {
return 0;
};
console.log(trueFactorial(5)); // 120
console.log(factorial(5)); // 0

这段就有意思了,
trueFactorial 变量被赋值为 factorial,所以console.log(trueFactorial(5));结果为120;
但是console.log(factorial(5)); 结果又为0;
trueFactorial 不受factorial方法重写的影响
这一个例子就帮我们记住了三个知识点:
1.函数名真的是指针
2.使用 arguments.callee 就可以让函数逻辑与函数名解耦
3.js有重写,莫得重载
6.caller属性
caller属性引用的是调用当前函数的函数,或者如果是 在全局作用域中调用的则为 null。
function outer() {
inner();
}
function inner() {
console.log(arguments.callee.caller);
}
outer();

第122篇: JS函数一些基本概念的更多相关文章
- UI5-技术篇-JS函数eval动态执行
<html lang="en"> <head> <meta charset="utf-8" /> <title> ...
- 学好js,这些js函数概念一定要知道
函数创建方式 1.声明方式 例如:function consoleTip (){ console.log("tip!"); } 2.表达式方式 例如:var consoleTip ...
- 前端总结·基础篇·JS(三)arguments、callee、call、apply、bind及函数封装和构造函数
前端总结系列 前端总结·基础篇·CSS(一)布局 前端总结·基础篇·CSS(二)视觉 前端总结·基础篇·CSS(三)补充 前端总结·基础篇·JS(一)原型.原型链.构造函数和字符串(String) 前 ...
- 如何编写高质量的 JS 函数(1) -- 敲山震虎篇
本文首发于 vivo互联网技术 微信公众号 链接:https://mp.weixin.qq.com/s/7lCK9cHmunvYlbm7Xi7JxQ作者:杨昆 一千个读者,有一千个哈姆雷特. 此系列文 ...
- 如何编写高质量的 JS 函数(2) -- 命名/注释/鲁棒篇
本文首发于 vivo互联网技术 微信公众号 链接:https://mp.weixin.qq.com/s/sd2oX0Z_cMY8_GvFg8pO4Q作者:杨昆 上篇<如何编写高质量的 JS 函数 ...
- 如何编写高质量的 JS 函数(3) --函数式编程[理论篇]
本文首发于 vivo互联网技术 微信公众号 链接:https://mp.weixin.qq.com/s/EWSqZuujHIRyx8Eb2SSidQ作者:杨昆 [编写高质量函数系列]中, <如何 ...
- 如何编写高质量的 JS 函数(4) --函数式编程[实战篇]
本文首发于 vivo互联网技术 微信公众号 链接:https://mp.weixin.qq.com/s/ZoXYbjuezOWgNyJKmSQmTw作者:杨昆 [编写高质量函数系列],往期精彩内容: ...
- js函数与作用域,了解函数基本概念
通过js基础语法了解到js的值包含数字,字符串和布尔值;js运算符分为算数,赋值,比较和逻辑运算符;js的流程控制包含条件判断if,switch选择;循环for while:下面js的函数及作用域,学 ...
- JS函数篇【2】
什么是函数 函数的作用,可以写一次代码,然后反复地重用这个代码. <h3 onload="add2(1,2,3);add3(4,5,6)"></h3> &l ...
- AntDesign-React与VUE有点不一样,第一篇深入了解React的概念之一:JSX
AntDesign-React与VUE有点不一样,第一篇深入了解React的概念之一:JSX 一.什么是JSX 使用JSX声明一个变量(REACT当中的元素): const element =< ...
随机推荐
- 手工创建一个带sticky模块的nginx镜像 并且实现容器化负载均衡的方法
最近想进行容器化运行的nginx反向代理负载均衡服务. 找了一下 dockerhub上面的 nginx 发现里面不包含 sticky模块. 会报错为: nginx: [emerg] unknown d ...
- UOS关闭激活提示: Your system is not activated. Please activate as soon as possible for normal use.
最近公司里面进行UOS的兼容性验证,但是系统总是会提示: Your system is not activated. Please activate as soon as possible for n ...
- 冷备份MySQL数据库并且使用Docker直接运行的操作过程
备份数据库 查看数据库的数据文件的位置 systemctl status mysqld 查看启动进程以及防水 /etc/my.conf 查看datadir 指向Mysql数据库的存储数据路径. 关闭数 ...
- SMFL 教程&个人笔记(2)
本文大部分来自官方教程的Google翻译 但是加了一点点个人的理解和其他相关知识 转载请注明 原文链接 :https://www.cnblogs.com/Multya/p/16317401.html ...
- 学习MySQL中DDL语句的修改字段与删除字段,删除表
连接本地mysql语句 mysql -hlocalhost -uroot -proot 显示表结构 语法:desc 表名 查看某一个表结构以及注释 语法:show create table 表名 sh ...
- vue2-vue3监听子组件的生命周期的两种方式
1.生命周期 生命周期是指:vue实例从创建到销毁这一系列过程.vue官网生命周期如下图所示: vue的生命周期有多少个 beforeCreate, created, beforeMount, mou ...
- 『Echarts』简介
目录 一.前言 二.『Echarts』简介 1. 什么是『Echarts』 三.数据可视化 四.『Echarts』 1.『Echarts』的作用 2.『Echarts』能绘制哪些图表 3.『Echar ...
- 21.13 Python 实现端口流量转发
端口流量转发(Port Forwarding)是一种网络通信技术,用于将特定的网络流量从一个端口或网络地址转发到另一个端口或地址.它在网络中扮演着一个非常重要的角色,在Python语言中实现端口转发非 ...
- 3.1 DLL注入:常规远程线程注入
动态链接库注入技术是一种特殊的技术,它允许在运行的进程中注入DLL动态链接库,从而改变目标进程的行为.DLL注入的实现方式有许多,典型的实现方式为远程线程注入,该注入方式的注入原理是利用了Window ...
- BAT大厂面试的100道考题【算法、源码、架构、中间件、设计模式、网络、项目】,过60分的不到10%
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 独生子女生娃,没救了! 考题:https://docs.qq.com/form/page/DT ...