JavaScript函数
程序中的foo,bar,baz
var foo ="xxxx"//变量
var bar = { //函数
name:"xxxx"
}
它们通常被用来作为函数、变量、文件的名词;
目前已经编程了计算机编程的术语一部分;
但是它们本身并没有特别的用途和意义;
常被称之为“伪变量”(metasyntactic variable)
认识JavaScript函数
----某种特定功能的代码封装
alert函数:浏览器弹出一个弹窗
prompt函数: 在浏览器弹窗中接收用户的输入
console.log函数:在控制台输入内容
String/Number/Boolean函数等
函数的使用步骤
◼ 函数的使用包含两个步骤:
声明函数——封装独立的功能
调用函数——享受封装的成果
◼ 声明函数,在JavaScript中也可以称为定义函数:
声明函数的过程是对某些功能的封装过程;
在之后的开发中,我们会根据自己的需求定义很多自己的函数;
◼ 调用函数,也可以称为函数调用:
调用函数是让已存在的函数为我们所用;
这些函数可以是刚刚自己封装好的某个功能函数;
当然, 我们也可以去使用默认提供的或者其他三方库定义好的函数;
◼ 函数的作用:
在开发程序时,使用函数可以提高编写的效率以及代码的重用;
函数的声明和调用
例如:
// 声明函数
// ()里可以传递参数
function foo() {
var info = {
name:"WebKing",
sex:"男",
age:"21"
};
console.log(info)
}
// 调用函数
// 函数可以进行多次调用,前提是你必须能找到这个函数
foo()
◼ 注意:
函数名的命名规则和前面变量名的命名规则是相同的;
函数要尽量做到见名知意(并且函数通常是一些行为(action),所以使用动词会更多一些);
函数定义完后里面的代码是不会执行的,函数必须调用才会执行;
◼ 调用函数通过函数名()即可:比如test()
◼ 函数的练习:
练习一:定义一个函数,打印一个人的个人信息
练习二:定义一个函数,函数中计算10和20数字的和,并且打印出结果
函数的参数
函数的参数:
函数,把具有独立功能的代码块组织为一个小模块,在需要的时候调用
函数的参数,增加函数的通用性,针对相同的数据处理逻辑,能够适应更多的数据
✓ 在函数内部,把参数当做变量使用,进行需要的数据处理
✓ 函数调用时,按照函数定义的参数顺序,把希望在函数内部处理的数据,通过参数传递
形参和实参:
形参(参数parameter):定义函数时,小括号中的参数,是用来接收参数用的,在函数内部作为变量使用
实参(参数argument):调用函数时,小括号中的参数,是用来把数据传递到函数内部用
例如:
<script>
// name,age,height 称之为函数的参数(形参)
function printInfo(name,age,height){
console.log(`mynameis ${name}`);
console.log(`my age is ${age}`);
console.log(`my height is ${height}`)
}
// 调用-"hdc","21","1.88"--->函数的实参
printInfo("hdc","21","1.88");
printInfo("kebo","30","1.98")
</script>
函数的返回值
回想我们之前使用的prompt函数,函数需要接受参数,并且会返回用户的输入:
◼ 所以说, 函数不仅仅可以有参数, 也可以有返回值:
使用return关键字来返回结果;
一旦在函数中执行return操作,那么当前函数会终止;
如果函数中没有使用return语句,那么函数有默认的返回值:undefined;
如果函数使用return语句,但是return后面没有任何值,那么函数的返回值也是:undefined;
arguments参数(JS高级再学习)
事实上在函数有一个特别的对象:arguments对象
默认情况下,arguments对象是所有(非箭头)函数中都可用的局部变量;
该对象中存放着所有的调用者传入的参数,从0位置开始,依次存放;
arguments变量的类型是一个object类型( array-like ),不是一个数组,但是和数组的用法看起来很相似;
如果调用者传入的参数多余函数接收的参数,可以通过arguments去获取所有的参数;
函数的递归调用
函数中调用函数
在开发中,函数内部是可以调用另外一个函数的。
◼ 既然函数中可以调用另外一个函数,那么函数是否可以调用自己呢?
当然是可以的;
但是函数调用自己必须有结束条件,否则会产生无限调用,造成报错;
例如:
<script>
function bar(){
console.log("bar函数执行")
}
function foo(){
console.log("foo函数执行")
// 调用自己的函数
bar()
}
foo()
</script>
函数的递归
事实上,函数调用自己还有一个专业的名词,叫做递归(Recursion)
◼ 在语言学方面,我们也可以描述为递归:
从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢!故事是什么呢?
递归读取上面的话;
◼ 递归是一种重要的编程思想:
将一个复杂的任务,转化成可以重复执行的相同任务;
◼ 案例:实现一个自己的幂函数pow(pow单词可以表示指数的意思)
我们可以用递归方法实现;
// 递归方法实现(必须有一个结束条件)
// 性能较低(占据过多的栈内存)
// 有点代码简洁
<!-- function pow1(x,n){
if (n === 1) {return x}
return x * pow1(x,n-1)
} -->
斐波那契数列 使用两个方法实现
// 斐波那契数列
// 数列:1 1 2 3 5 8 13 21 34 55
// 索引:1 2 3 4 5 6 7 8 9 10
// 递归 实现
function fibonacci(n){
if (n === 1 || n === 2) return 1
return fibonacci(n-1) + fibonacci(n-2)
}
console.log(fibonacci(10))
// for 循环实现
function fibonacci1(n){
if (n ===1 || n === 2) return 1
var n1 = 1
var n2 = 1
var result = 0
for (var i = 3 ; i<=n ; i++){
result = n1+n2;
n1 = n2
n2 =result
}
return result
}
局部和全局变量
在JavaScript(ES5之前)中没有块级作用域的概念,但是函数可以定义自己的作用域。
作用域(Scope)表示一些标识符的作用有效范围(所以也有被翻译为有效范围的);
函数的作用域表示在函数内部定义的变量,只有在函数内部可以被访问到;
◼ 外部变量和局部变量的概念:
定义在函数内部的变量,被称之为局部变量(Local Variables)。
定义在函数外部的变量,被称之为外部变量(Outer Variables)。
◼ 什么是全局变量?
在函数之外声明的变量(在script中声明的),称之为全局变量。
全局变量在任何函数中都是可见的。
通过var声明的全局变量会在window对象上添加一个属性(了解);
◼ 在函数中,访问变量的顺序是什么呢?
优先访问自己函数中的变量,没有找到时,在外部中访问。
◼ 关于块级作用域、作用域链、变量提升、AO、VO、GO等概念我们后续将进行学习。
概念
// 全局变量:在全局(script元素中)定义一个变量,那么这个变量是可以在定义以后的任何范围内被访问到的,那么这个变量就被称之为是一个全局变量
var message = "Hello World"
// 在函数中访问message
function foo(){
// 外部变量:在函数内部取访问函数之外的变量,访问的变量称之为外部变量
console.log(message)
// 2.局部变量:在函数内部定义的变量,只有在函数内部才能进行访问,称之为局部变量(布局变量)
var nickName = "webKing"
function hi(){
// message是一个外部变量
console.log(message)
// nickname也是一个外部变量
console.log(nickName)
}
hi()
}
foo()
案例
//message 在哪一个范围内可以被使用,称之为message的作用域
// 全局变量:全局作用域
var message = "Hello World"
if(true){
console.log(message)
}
function foo(){
console.log(message)
}
foo()
// 2.在ES5之前是没有块级作用域(var定义的变量是没有块级作用域)
{
var cont = 100
console.log("在代码块中访问count:",cont)
}
console.log("在代码块外访问count:",cont)
// for循环的代码块也是没有自己的作用域的
for (var i = 0;i<3;i++){
var foo = "foo"
}
console.log("for循环外面访问foo",foo)
console.log("for循坏外面访问i:",i)
// 3.在ES5之前函数代码块是会形成自己的作用域
// 意味着在函数内部定义的变量外面是访问不到的
function test(){
var bar = "bar"
}
test()
// console.log("test函数外面方位bar:",bar)-->访问不到
// 函数有自己的作用域:函数内部定义的变量只有自己能访问到
function sayHello(){
var nickName = "kebo"
console.log("sayHello函数内部访问nickName:",nickName)
function hi(){
console.log("hi function!")
console.log("在hi函数内访问nickname",nickName)
}
hi()
}
sayHello()
console.log("sayHello函数外面访问nickName:",nickName)--->访问不到
变量的访问顺序
<script>
// 变量访问顺序
// 先查找内部变量 再查找上层作用域外部变量 再查找全局变量 再查找window对象 没找到就会报错
var message = "Hello world"
function sayHello(){
var message = "Hello CoderHdc"
function hi(){
var message = "Hi kobe"
console.log(message)
}
hi()
}
sayHello()
</script>
函数表达式的写法
◼ 在JavaScript中,函数并不是一种神奇的语法结构,而是一种特殊的值。
前面定义函数的方式,我们称之为函数的声明(Function Declaration);
◼ 还有另外一种写法是函数表达式(Function Expressions):
<!-- 函数本身也是一种对象类型 -->
var foo = function(){
console.log("foo函数")
}
◼ 注意,function 关键字后面没有函数名
函数表达式允许省略函数名。
◼ 无论函数是如何创建的,函数都是一个值(这个值的类型是一个对象,对象的概念后面会讲到)。
◼ 在JavaScript开发中,我们可以将函数作为头等公民。
函数声明vs函数表达式
◼ 在开发中,函数的声明和函数表达式有什么区别,以及如何选择呢?
◼ 首先,语法不同:
函数声明:在主代码流中声明为单独的语句的函数。
函数表达式:在一个表达式中或另一个语法结构中创建的函数。
◼ 其次,JavaScript创建函数的时机是不同的:
函数表达式是在代码执行到达时被创建,并且仅从那一刻起可用。
在函数声明被定义之前,它就可以被调用。
✓ 这是内部算法的原故;
✓ 当JavaScript 准备运行脚本时,首先会在脚本中寻找全局函数声明,并创建这些函数;
◼ 开发中如何选择呢?
当我们需要声明一个函数时,首先考虑函数声明语法。
它能够为组织代码提供更多的灵活性,因为我们可以在声明这些函数之前调用这些函数。
函数的头等公民
◼ 头等函数(first-class function;第一级函数)是指在程序设计语言中,函数被当作头等公民。
这意味着,函数可以作为别的函数的参数、函数的返回值,赋值给变量或存储在数据结构中;
有人主张也应包括支持匿名函数(待会儿会讲到);
◼ 通常我们对作为头等公民的编程方式,称之为函数式编程
JavaScript就是符合函数式编程的语言,这个也是JavaScript的一大特点;
◼ 比如:函数可以在变量和变量之间相互进行赋值
function foo(){
console.log("foo函数执行")
}
var bar = foo
bar()
回调函数
◼ 既然函数可以作为一个值相互赋值,那么也可以传递给另外一个函数。
function foo(fn){
// 通过fn去调用bar函数的过程,称之为函数的回调
fn()
}
function bar(){
console.log("bar函数被执行了")
}
foo(bar)
◼ foo这种函数我们也可以称之为高阶函数(Higher-order function);
◼ 高阶函数必须至少满足两个条件之一:
接受一个或多个函数作为输入;
输出一个函数;
◼ 匿名(anonymous)函数的理解:
如果在传入一个函数时,我们没有指定这个函数的名词或者通过函数表达式指定函数对应的变量,那么这个函数称之为匿名
函数
回调函数案例
// 函数回调的案例
// function request(url,callbak){
// console.log("根据URL 向服务器发送网络请求")
// console.log("需要花费较长的时间来拿到对应的结果")
// var list = ["JavaScript","JavaScript学习","JavaScript高级编程"]
// callbak(list)
// }
// function handleRequest(res){
// console.log("在函数中拿到结果",res)
// }
// request("http://www.baidu.com/abc",handleRequest)
// 函数回调案例重构
function request(url,callbak){
console.log("根据URL 向服务器发送网络请求")
console.log("需要花费较长的时间来拿到对应的结果")
var list = ["JavaScript","JavaScript学习","JavaScript高级编程"]
callbak(list)
}
// 传入的函数是没有名字的称作匿名函数
request("http://www.baidu.com/",function (res){
console.log("在函数中拿到结果",res)
})
立即执行函数使用
什么是立即执行函数?
专业名字:Immediately-Invoked Function Expression(IIFE 立即调用函数表达式)
表达的含义是一个函数定义完后被立即执行;
✓ 第一部分是定义了一个匿名函数,这个函数有自己独立的作用域。
✓ 第二部分是后面的(),表示这个函数被执行了
(function(){
console.log("立即执行函数")
})()
立即执行函数作用
会创建一个独立的执行上下文环境,可以避免外界访问或修改内部的变量,也避免了对内部变量的修改
立即执行函数和普通代码的区别
1.在立即执行函数定义的变量是有作用域的
案例--监听按钮点击次数
1.获取一个按钮监听点击
// querySelector(".btn") 拿到一个btn的按钮
// querySelectorAll 拿到所有class为btn的按钮
// ES6 的做法
var btnEl = document.querySelectorAll(".btn")
for (let i = 0 ;i <btnEl.length;i++){
var btn = btnEl[i];
btn.addEventListener("click",function(){
console.log(`按钮${i+1}发送点击`)
})
}
// ES5做法
var btnEls = document.querySelectorAll(".btn")
for (var i = 0;i<btnEls.length ;i++){
var btn= btnEls[i];
(function(m){
btn.onclick = function(){
console.log(`按钮${m+1}被点击`)
}
})(i)
}
立即执行函数其他写法
// 写法一
(function(){
console.log("写法一立即执行函数")
})();
// 写法二
+function(){
console.log("写法二立即执行函数")
}();
// 写法三
(function(){
console.log("写法三立即执行函数")
}());
代码规范
(),{},[]使用
{}代码块/对象类型
()控制优先级(2+3)*5/函数的调用/函数的参数
[]定义数组/从数组-对象中取值/对象的计算属性
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· Vue3状态管理终极指南:Pinia保姆级教程