详解JavaScript函数(javascript function函数)
myzbx 2025-06-15 18:01 14 浏览
Js中的函数
函数分类:系统函数和自定义函数,在JS中,函数也是一种单独的数据类型。
1.系统函数/全局函数
在JS中总有一些函数是不属于任何一个对象或者类的,这样的函数我们就叫做全局函数
全局函数的访问方式: 直接通过方法访问
常用的全局函数
eval(): 计算JavaScript字符串,并把它作为脚本代码来执行
encodeURI():把字符串编码成URI
decodeURI():解码某个编码的URI
isNaN() 检查某个值是否是数字
如果参数是一个数字,返回false
如果参数不是一个数字,返回true
parseInt() 解析一个字符串为整数
parseFloat() 解析一个字符串为小数
2.自定义函数
在Java中如何定义函数呢?
访问权限修饰符 返回值类型 方法名(参数类型 变量名1, 参数类型 变量名2...) [throws 异常类名]{
方法体;
return 返回值;
}
在JS里面定义函数(满足方法定义的二要素: 参数列表 方法名)
三种方式
1.采用function关键字来定义
格式:
function 函数名(变量名,变量2...){
函数体;
返回值;
}
2.采用匿名定义的方式来定义函数【也称为函数表达式】
var 函数名 = function(参数列表){
函数体;
返回值;
}
3.采用一个内置对象Function来创建(动态函数)
var 函数名 = new Function("参数列表", "函数体");
3. 函数调用
1.函数调用的时候参数可以传递多个,可以和形参不匹配
注意:
如果实参的个数小于形参的个数,未被赋值的形参的值为undefined.
如果实参的个数大于或者等于形参的个数,显示实际结果
其实你传的参数多了都会被一个叫做arguments数组接收掉
2.如果函数重名了,在Java里面叫做重载,在JS里面不存在重载,js会调用最后一个重名的方法,也就是最后一个方法会覆盖之前的重名方法
JavaScript中,arguments对象是比较特别的一个对象,实际上是当前函数的一个内置属性。也就是说所有函数都内置了一个arguments对象,arguments对象中存储了传递的所有的实参。arguments是一个伪数组,因此及可以进行遍历。
函数的实参个数和形参个数可以不一致,所有的实参都会存储在函数内部的arguments类数组对象中。
3.如果函数没有设置 return语句 ,那么函数有默认的返回值undefined;如果函数使用 return语句,但是return后面没有任何值,那么函数的返回值也是undefined。
js里面是不存在重载的
如果我想要实现重载的效果,怎么做? (理解即可)
function getMax(a, b, c, d){
// arguments数组接收所有的参数
document.write(arguments.length + "<br />");
if(arguments.length == 1){
return a;
} else if(arguments.length == 2){
return a > b ? a : b;
} else if(arguments.length == 3){
return a > b ? (a > c ? a : c) : (b > c ? b : c);
} else if(arguments.length == 4){
return Math.max(a, b, c, d);
} else {
return 0;
}
}
4. 作用域
作用域:变量可以起作用的范围。
如果变量定义在一个函数内部,只能在函数内部被访问到,在函数外部不能使用这个变量,函数就是变量定义的作用域。
任何一对话括号{}中的语句集都属于一个块,在这之中定义的所有变量在代码块外都是不可见的,我们称之为块级作用域。 JavaScript没有块级作用域的的概念,只有函数作用域,现阶段可以认为没有块级作用域.
// 定义函数
function fun(){
var a = 1;
console.log(a);
}
fun();
console.log(a); // 报错
错误如下所示:
作用域链
只有函数可以制造作用域结构, 那么只要是代码,就至少有一个作用域, 即全局作用域。凡是代码中有函数,那么这个函数就构成另一个作用域。如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域。
将这样的所有的作用域列出来,可以有一个结构: 函数内指向函数外的链式结构。就称作作用域链。
// 案例1:
function f1() {
function f2() {
}
}
var num = 456;
function f3() {
function f4() {
}
}
作用域链如下所示:
再来看第二个案例
// 案例2
function f1() {
var num = 123;
function f2() {
console.log(num);
}
f2();
}
var num = 456;
f1();
如下图所示:
程序在遇到一个变量时,使用时作用域查找顺序,不同层次的函数内都有可能定义相同名字的变量,一个变量在使用时,会优先从自己所在层作用域查找变量,如果当前层没有变量定义会按照顺序从本层往外依次查找,直到找到第一个变量定义。整个过程中会发生内层变量遮蔽外层变量的效果,叫做“遮蔽效应”。
// 定义全局变量
var a = 2;
// 定义函数
function fun(){
var a = 1;
function fun1(){
var a = 3;
console.log(a);
}
console.log(a);
fun1();
}
fun();
console.log(a);
执行结果为:
5. 全局变量和局部变量
局部变量:定义在函数内部的变量,只能在函数作用域内部被访问到,在外面不能访问的。
函数的参数本质是一个变量,也有自己的作用域,函数的参数也是属于函数自己内部的局部变量,只能在函数内部被使用,在函数外面没有定义
全局变量:从广义上来说,也是一种局部变量,定义在全局的变量,作用域范围是全局,在整个js程序任意位置都能够被访问到,在定义后所有script标签都能访问。
6、预解析
JavaScript代码的执行是由浏览器中的JavaScript解析器来执行的。JavaScript解析器执行JavaScript代码的时候,分为两个过程:预解析过程和代码执行过程。
预解析过程:
1. 把变量的声明提升到当前作用域的最前面,只会提升声明,不会提升赋值。
2. 把函数的声明提升到当前作用域的最前面,只会提升声明,不会提升调用。
3. 先提升var,再提升function。
JavaScript的执行过程:在预解析之后,根据新的代码顺序,从上往下按照既定规律执行js代码。
5.1 变量声明提升
在预解析过程中,所有定义的变量,都会将声明的过程提升到所在的作用域最上面,在将来的代码执行过程中,按照先后顺序会先执行被提升的声明变量过程。
提升过程中,只提升声明过程,不提升变量赋值,相当于变量定义为赋值,变量内存储undefined值。
因此,在js中会出现一种现象,在前面调用后定义的变量,不会报错,只会使用undefined值。
// 变量先使用
console.log(a);
// 后定义
var a = 1;
运行结果如下所示:
预解析后的代码执行效果,等价于:
var a;
// 变量先使用
console.log(a);
// 后定义
a = 1;
5.2 函数声明提升
在预解析过程中,所有定义的函数,都会将声明的过程提升到所在的作用域最上面,在将来的代码执行过程中,按照先后顺序会先执行被提升的函数声明过程。
在预解析之后的代码执行过程中,函数定义过程已经在最开始就会执行,一旦函数定义成功,后续就可以直接调用函数。
因此,在js中会出现一种现象,在前面调用后定义的函数,不会报错,而且能正常执行函数内部的代码。
// 函数声明提升
// 先调用函数
fun();
// 后定义函数
function fun(){
console.log(1);
}
执行结果如下所示:
函数表达式:进行的是变量声明提升,而不是函数声明提升。提升后变量内部存的是一个undefined。在前面进行函数方法调用,数据类型会提示错误。
// 先调用函数表达式的变量名
console.log(fun);
fun();
// 后定义函数
var fun = function(){
console.log(1);
};
执行结果如下所示:
建议:定义函数时,最好使用function关键字定义方式,这样函数声明提升可以永远生效。
应用:函数声明提升可以用于调整代码的顺序,将大段的定义过程放到代码最后,但是不影响代码执行效果。
5.3 提升顺序
预解析过程中,先提升var变量声明,再提升function函数声明。
假设出现变量名和函数名相同,那么后提升的函数名标识符会覆盖先提升的变量名,那么在后续代码中出现调用标识符时,内部是函数的定义过程,而不是undefined。
// 函数声明提升优先于变量声明提升
console.log(fun);
function fun(){
console.log(1);
}
var fun = 2;
执行结果如下所示:
如果调用标识符的过程在源代码函数和变量定义后面,相当于函数名覆盖了一次变量名,结果在执行到变量赋值时,又被新值覆盖了函数的值,那么在后面再次调用标识符,用的就是变量存的新值。
var fun = 2;
function fun(){
console.log(1);
}
console.log(fun);
执行结果如下:
预解析后的代码执行效果,等价于:
var fun;
//函数定义先覆盖变量定义
function fun(){
console.log(1);
}
//变量再次赋值,覆盖函数定义
fun = 2;
console.log(fun);
建议:不要书写相同的标识符给变量名或函数名,避免出现覆盖。
7.IIFE
IIFE:immediately-invoked function expression,叫做即时调用的函数表达式,也叫做自调用函数,表示函数在定义时就立即调用。
之前学过的函数调用方式:函数名或函数表达式的变量名后面加()运算符。
函数关键字形式即时调用:
function fun(){
console.log(1);
}();
执行结果如下所示:
函数表达式形式即时调用:
var foo = function(){
console.log(1);
}();
执行结果如下所示:
函数使用函数表达式形式可以实现立即执行,原因是因为函数表达式定义过程中,将一个函数矮化成了一个表达式,后面加()运算符就可以立即执行。
启发:如果想实现IIFE,可以想办法将函数矮化成表达式。
函数矮化成表达式的方法,可以让函数参与一些运算,也就是说给函数前面加一些运算符。
数学运算符:+ - ()
逻辑运算符:!非运算
// IIFE的结构
+function fun(){
console.log(1);
}();
-function fun(){
console.log(1);
}();
(function fun(){
console.log(1);
})();
!function fun(){
console.log(1);
}();
IIFE结构可以关住函数的作用域,在结构外面是不能调用函数的。
(function fun(){
console.log(1);
})();
fun();
IIFE最常用的是()运算符,而且函数可以不写函数名,使用匿名函数。
(function(a){
console.log(a);
})(1);
8.几种特殊函数总结
函数本质实际上是对象,也是一种类型,叫做函数类型:它们能被“存储”在变量中,能作为函数参数被传递,能在函数中被创建,能从函数中返回;
回调函数:作为参数传递的函数
需要注意的很重要的一点是回调函数并不会马上被执行。它会在包含它的函数内的某个特定时间点被“回调”(就像它的名字一样)
// 回调函数:作为参数传递的函数
// 1.匿名函数作为回调函数 var fun = function(a, b, callback) {
var sum = a + b;
// 调用回调函数
callback(sum);
}
fun(10, 20, function(sum){
alert(sum);
});
// 2.命名函数作为回调函数 var fun = function(a, b, callback) {
var sum = a + b;
// 调用回调函数
callback(sum);
}
function call(sum) {
alert(sum);
}
fun(10, 20, call);
匿名函数:没有函数名的函数
// 匿名函数:没有函数名的函数 var fun = function() {
alert("匿名函数");
}();
(function (){
//由于没有执行该匿名函数,所以不会执行匿名函数体内的语句。
console.log("匿名函数");
})();
匿名回调函数:这个方法作为参数传递而且还没有方法名
var fun = function(a, b, callback) {
var sum = a + b;
// 调用回调函数
callback(sum); } fun(10, 20, function(sum){
alert(sum);
});
私有函数:定义在函数内部的函数.
保证函数的内部代码私有性。
一个函数执行多个逻辑
function method() {
function method2() {
alert("method2");
}
function method3() {
alert("method3");
}
alert("method");
method2();
method3();
}
method();
返回函数的函数
function method() {
alert("method");
return function() {
alert("返回匿名函数");
};
}
alert(method());
method()();
自调函数:定义()()
第一个小括号是函数定义
第二个小括号是函数调用.
(function() {
alert("自调函数");
})();
(function(x){
alert(x);
})(1);
相关推荐
- 零基础入门AI智能体:详细了解什么是变量类型、JSON结构、Markdown格式
-
当品牌跳出固有框架,以跨界联动、场景创新叩击年轻群体的兴趣点,一场关于如何在迭代中保持鲜活的探索正在展开,既藏着破圈的巧思,也映照着与新一代对话的密码。在创建AI智能体时,我们会调用插件或大模型,而在...
- C# 13模式匹配:递归模式与属性模式在真实代码中的性能影响分析
-
C#13对模式匹配的增强让复杂数据处理代码更简洁,但递归模式与属性模式的性能差异一直是开发者关注的焦点。在实际项目中,选择合适的模式不仅影响代码可读性,还可能导致执行效率的显著差异。本文结合真实测试...
- 零基础快速入门 VBA 系列 6 —— 常用对象(工作簿、工作表和区域)
-
上一节,我介绍了VBA内置函数以及如何自动打字和自动保存文件。这一节,我们来了解一下Excel常用对象。Excel常用对象Excel有很多对象,其中最常用也最重要的包括以下3个:1.Workbo...
- 不同生命数字的生肖龙!准到雷普!
-
属龙的人总在自信爆棚和自讨苦吃之间反复横跳?看完这届龙宝宝的日常我悟了。属龙的人好像天生自带矛盾体:领导力超强可人缘时好时坏,工作雷厉风行却总在爱情里翻车。关键年份的龙性格差异更大——76年龙靠谱但不...
- 仓颉编程语言基础-面向对象编程-属性(Properties)
-
属性是仓颉颉中一种强大的机制,它允许你封装对类(或接口interface、结构体struct、枚举enum、扩展extend)内部状态的访问。它看起来像一个普通的成员变量(字段),但在其背后,它通过...
- Python中class对象/属性/方法/继承/多态/魔法方法详解
-
一、基础入门:认识类和对象1.类和对象的概念在Python中,类(class)是一种抽象的概念,用于定义对象的属性和行为,而对象(也称为实例)则是类的具体表现。比如,“汽车”可以是一个类,它有...
- VBA基础入门:搞清楚对象、属性和方法就成功了一半
-
如果你刚接触VBA(VisualBasicforApplications),可能会被“对象”“属性”“方法”这些术语搞得一头雾水。但事实上,这三个概念是VBA编程的基石。只要理解它们之间的关系,...
- P.O类型文推荐|年度编推合集(一百九十五篇)
-
点击左上方关注获取更多精彩推文目录2019年度编推35篇(1V1)《悖论》作者:流苏.txt(1V1)《桂花蒸》作者:大姑娘浪.txt(1V1)《豪门浪女》作者:奚行.txt...
- Python参数传递内存大揭秘:可变对象 vs 不可变对象
-
90%的Python程序员不知道,函数参数传递中可变对象的修改竟会导致意想不到的副作用!一、参数传递的本质:对象引用传递在Python中,所有参数传递都是对象引用的传递。这意味着函数调用时传递的不是对...
- JS 开发者必看!TC39 2025 最新动向,这些新语法要火?
-
大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发,您的支持是我不断创作的动力。TC39第...
- 2025 年值得尝试的 5 个被低估的 JavaScript 库
-
这些JavaScript库可能不会在社交媒体或HackerNews上流行起来,但它们会显著提高您的工作效率和代码质量。JavaScript不再只是框架。虽然React、Vue和Sv...
- Python自动化办公应用学习笔记30—函数的参数
-
一、函数的参数1.形参:o定义:在函数定义时,声明在函数名后面括号中的变量。o作用:它们是函数内部的占位符变量,用于接收函数被调用时传入的实际值。o生命周期:在函数被调用时创建,在函数执...
- 16种MBTI人格全解析|测完我沉默了三秒:原来我是这样的人?
-
MBTI性格测试火了这么久,你还不知道自己是哪一型?有人拿它当社交话题,有人拿它分析老板性格,还有人干脆当成择偶参考表。不废话,今天我一次性给你整理全部16种MBTI人格类型!看完你不仅能知道自己是谁...
- JS基础与高级应用: 性能优化
-
在现代Web开发中,性能优化已成为前端工程师必须掌握的核心技能之一。本文从URL输入到页面加载完成的全过程出发,深入分析了HTTP协议的演进、域名解析、代码层面性能优化以及编译与渲染的最佳实践。通过节...
- 爱思创CSP-J/S初赛模拟赛线上开赛!助力冲入2024年CSP-J/S复赛!
-
CSP-J/S组初赛模拟赛爱思创,专注信奥教育19年,2022年CSP-J/S组赛事指定考点,特邀NOIP教练,开启全真实CSP-J/S组线上初赛模拟大赛!一、比赛对象:2024年备考CSP-J/S初...
- 一周热门
- 最近发表
-
- 零基础入门AI智能体:详细了解什么是变量类型、JSON结构、Markdown格式
- C# 13模式匹配:递归模式与属性模式在真实代码中的性能影响分析
- 零基础快速入门 VBA 系列 6 —— 常用对象(工作簿、工作表和区域)
- 不同生命数字的生肖龙!准到雷普!
- 仓颉编程语言基础-面向对象编程-属性(Properties)
- Python中class对象/属性/方法/继承/多态/魔法方法详解
- VBA基础入门:搞清楚对象、属性和方法就成功了一半
- P.O类型文推荐|年度编推合集(一百九十五篇)
- Python参数传递内存大揭秘:可变对象 vs 不可变对象
- JS 开发者必看!TC39 2025 最新动向,这些新语法要火?
- 标签列表
-
- HTML 简介 (30)
- HTML 响应式设计 (31)
- HTML URL 编码 (32)
- HTML Web 服务器 (31)
- HTML 表单属性 (32)
- HTML 音频 (31)
- HTML5 支持 (33)
- HTML API (36)
- HTML 总结 (32)
- HTML 全局属性 (32)
- HTML 事件 (31)
- HTML 画布 (32)
- HTTP 方法 (30)
- 键盘快捷键 (30)
- CSS 语法 (35)
- CSS 轮廓宽度 (31)
- CSS 谷歌字体 (33)
- CSS 链接 (31)
- CSS 定位 (31)
- CSS 图片库 (32)
- CSS 图像精灵 (31)
- SVG 文本 (32)
- 时钟启动 (33)
- HTML 游戏 (34)
- JS Loop For (32)