函数
函数的作用:
函数:function,是被设计为执行特定任务的代码块
函数可以把具有相同的或者相似逻辑的代码“包裹”起来,通过函数调用执行,为了代码的多次使用(重用)(复用) 一次编写,多次使用
函数的基本使用
函数的声明语法
function 函数名(){
函数体(函数要做的事)
}
例如:
function sayHi(){
document.write('hhai~~~~')
}
函数的调用:
函数只声明,不调用,不发挥作用,代码不执行,
函数名()
例如:
sayHi()
特点:
1、先声明,再调用 或者 先调用,在声明
2、输出函数名,会输出整个函数的4个组成部分
3、typeOf 函数名===>‘function’,函数也是一种数据类型,函数(function)类型
4、函数的取名
1、与变量名一致
2.推荐以动词开头,如下表:
动词 | 含义 |
---|---|
can | 判断是否可执行某个动作 |
has | 判断是否含义为某个值 |
is | 判断是否为某个值 |
get | 获取某个值 |
set | 设置某个值 |
load | 加载某些数据 |
有参数的函数
参数列表:
传入数据列表
声明这个函数需要传入几个数据
多个数据用逗号隔开
function 函数名(参数列表){
函数体
}
//调用
函数名(传递的参数列表); //有几个参数就传几个参数 多个数据使用逗号隔开
有参函数的执行过程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jZ2wbY4U-1630218668269)(F:\练习\手册\笔记\JavaScript\img\有参函数的执行过程.png)]
案例
// 计算公里数
let sd=+prompt('请输入时速')
let time=+prompt('请输入开车时长:')
function getDistance(sd, time) {
return sd * time
}
console.log(getDistance(90, 3))
有返回值的函数
返回值的使用
获取返回值有两种方式
1、直接使用
2、把函数的执行结果 赋值 给 某个变量
3、当对函数的返回值需要多次使用的时候,使用第二种方式,因为这个变量可以使用多次,二函数只需要执行一次。如果选择第一种方式,缺点是没获取一次返回值,都需要全新的去执行一次函数体,效率相比第二种反思略低,当需要对函数的返回值使用多次的时候,推荐使用第三种方式
function getSum (x,y){
return x * y
}
//直接使用
getSum(10,30) //300
//把函数的执行结果 赋值 给 某个变量
let re=getSum(10,30)
console.log(re)
return的细节:
1、return:后面的代码立即结束,不执行后面的代码
2、当函数内部没有return或者return没有跟数据,此时函数返回undefined
let num = getSum(10,40)
console.log(num)
function gertSum(num1,num2){
return num1 + num2
document.write('执行完毕')
}
返回值的案例:
//请输入总额
let total=+prompt('请输入总额:')
let rebFee=+prompt('请输入食宿费:')
let liveFee=+prompt('请输入生活费:')
//调用
let balance=getBalance(total,rebFee,liveFee)
alert(balance)
//声明
function getBalance(total,rebFee,liveFee){
return total - rabFee - liveFee
}
内置函数
什么是内置函数
JavaScript内部分装好的一些函数,让开发者直接调用就可以完成对应的功能
parseInt():
1、从字符串·中提取整数
当字符串以非数字开发,就不可以提取出来
2、对一个整数进行取整
console.log(parseInt('100')) //100
console.log(parseInt('100.5s')) //100
console.log(parseInt('100.500px200')) //100
console.log(parseInt('abc100.5px'))//NAN
parseFloat()
从字符串中提取出带小数的数字**(用法与parseInt一样)**
console.log(parseFloat('100')) //100
console.log(parseFloat('100.5')) //100.5
console.log(parseFloat('100.5px200')) //100.5
console.log(parseFloat('abc100.5px'))//NAN
内置函数案例
//输入秒数:
let seconds=+prompt('请输入总秒数:')
//单位换算
let hour=parseInt(seconds/60/60)
let minute=parseInt(seconds/60%60)
let second=seconds%60
//输出
document.write(`${seconds}秒转换后是${hour}小时${minute}分钟${second}秒`)
高阶函数
函数自己不会执行,必须调用才可以执行。调用函数的方式,就在函数名后面加小括号。
函数分为具名函数和匿名函数,
具名函数是指函数要有具体的名称,匿名函数是指没有名字的函数
具名函数
//具有函函数 有名字
function foo(){
console.log('foo函数正在被执行中')
}
foo()
匿名函数
注意函数其实也是数据,也是值
let fn=function () {
console.log('好多代码')
}
fn()
表达式函数
注意:
1、定义函数的参数是形参,调用函数的参数是实参、
2、返回值是把这个值返回到调用函数的位置(返回给调用者),
3、如果return后面没有写值,就会返回undefined,
4、如果函数中不写return,那么函数在执行完成所有代码之后会把undefined返回
let fun = function (a,b){
console.log(a,b)
return a * b
}
fun(1,3)
自调用函数
自执行函数,立即执行函数
!(function(){
console.log('abc')
})()
回调函数
给别的函数当参数的函数叫回调函数
函数A作为参数给B函数当参数,就叫做回调函数
function fn(){
console.log('obk')
}
let n=function() {
console.log('123')
}
fn(n)
回调函数的使用场景:
//定时器
setInterval(function(){
console.log('abc')
},1000)
命名空间
命名空间本质上是一个普通对象,将具有关联性的变量和函数封装起来作为该对象的属性或方法
解决了变量污染的问题
let zs={
uname:'张三',
sex:'男',
age:19
}
let ls ={
uname:'李四',
sex:'女',
age:18
}
命名空间的案例
//封装命名空间
let zs={
data:new DatE(),
year:function(){
//注意:属性不可以直接拿出来使用,方法同理
this.data.getFullYear();
}
}
console.log(zs.data)
递归函数
递归函数:函数内部自己调用自己,并且通过条件控制避免陷入死循环,
function fn (n){
//条件控制必须要有,否则就会进入死循环
if(n==0){
return;
}
fn(n-1)
document.write(n)
}
fn(3)
递归函数中的三个特征:
重复执行
递归练习
//求任意一个数的阶乘
function jc(n){
//条件控制,必须要有否则会进入死循环
if(n==1){
return
}
return n * jc(n-1)
//6 * jc(5);
//6 * 5 * jc(4);
//6 * 5 * 4 *jc(3)
//6 * 5 * 4 * 3 * jc(2)
//6 * 5 * 4 * 3 * 2 * 1
}
console.log(jc(6))
//求兔子的数列:1、1、2、3、5、8、13、21、34
//第n个月有多少对兔子
递归点:每个月的兔子的都是前两个月的兔子数相加
出口点:第一个月和第二个月兔子书都是一
function tuzi(n){
if(n==1||n==2){
return 1
}
return tuzi(n-1)+ tuzi(n-2)
//tuzi(5)+ tuzi(4)
//tuzi(4)+ tuzi(3)+tuzi(4)
//tuzi(3)+ tuzi(2)+tuzi(3) + tuzi(4)
}
console.log(tuzi(6))
作用域:
一个变量的使用范围
作用域的三个方式
局部作用域:函数内部就是局部作用域
//形参也就是相当于局部变量
function fn(a){
//1、函数在执行的时候先在内存中开辟新的作用域空间
//2、当执行完毕函数之后,会关闭作用域空间
let n=132;
console.log(n)
}
fn()
//局部变量只能在当前函数内部使用,否则会出现报错
console.log(n)
块级作用域
ES6中可以直接使用大括号里的块级作用域,在块级作用域中声明的变量不能在外部使用,否则会报错
let 声明的变量具有块级作用域,var声明的变量不具有块级作用域
{
let n =3
console.log(n)
n+=6
}
//块级作用域
if(true){
let num=123
}
console.log(num) //会报错
//块级作用域
for(let i=1;i<100;i++){
let num=666
}
console.log(num)
全局作用域:函数外部就是全局作用域,函数外部的范围
全局变量:在全局作用域声明的变量称为全局变量,这个变量可以在任何地方使用
let n=3;
function fn(){
console.log(n)
}
fn()
声明变量
var 、let 、const
var声明的变量相当于给window添加了一个属性,let 不会追加到window。声明的var不具有块级作用域,let具有块级作用域。var可以重复声明定义,let声明的变量不可以重复定义。
const和let区别,原来定义常量,不可以改值,let 可以该值,定义的常量必须要初始化值,let可以不设置值 建议:常量名字应为是不可以改动的值,所特有常量名建议用大写,一般使用请况》:用于定义固定不变的值
作用域链:
是由作用域串联起来的链状结构
作用:提供我们查找变量的机制
let n = 1
let num=2
function fn () {
console.log(n)
function(num){
console.log(num)
}
fn()
}
fn()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JwJaUrCi-1630218668273)(F:\练习\手册\笔记\JavaScript\img\作用域链.png)]
闭包
概念:一个作用域有权访问另外一个作用域的局部变量,称为闭包,也就是子函数就可以到访问父作用域的局部变量
作用:让一个变量的作用范围的延伸\2222222222222222
当函数执行完毕之后,会关闭作用域空间,同时销毁局部变量
function fun(){
let n = 2;
console.log(n)
function fn(){
//子方法函数可以使用n的值
console.log(num)
}
fn()
}
fun()
//这边就不能获取到n的值,就会报错
console.log(n)
预解析
代码在执行的之前先要预解析 从上往下执行
在代码执行之前把变量和函数会提前解析到当前作用域的在最前面 ,任何一个作用域在执行代码之前都要先预解析
变量:带有声明的变量,只定义不赋值
函数预解析:带有名字的函数,只定义不调用
/*
函数:只定义不调用
function fn(){
console.log(123)会在内存中开辟一块空间
}
*/
function fn(){
console.log(123)
}
fn()
参数
动态参数
当参数不固定的时候,就要使用动态参数 ,传入任意歌参数都可以打印出来,如果函数的参数不固定,那么就不要写形参接收
在函数中,有一个特殊的对象arguments() 用于接收所有的实参
function fn() {
console.log(arguments) //会打印出一个伪数组
//取出每个值 for遍历
for(let i=0;i<arguments.length;i++){
console.log(arguments[i])
}
}
fn(1,2,3,4,5,6,6,78,0,1)
//写一个函数,求任意个数的和
function getSum() {
//求和
let sum=0
for(let i=0;i<arguments.length;i++){
sum+=arguments[i]
}
}
getsum(1,2,4,1313,324243)
剩余参数
…剩余参数写法,只能写在最后面的位置,代码如下:
//第一个参数a接收 第二个参数b接收 剩余的所有参数c接收
function sum(a,b,...c){
console.log(a,b,c)
}
sum(1,2,3,45,6)
//写一个函数,求任意两个数的和
function getsum (..a){
let ssum=0;
for(let i=0;i<a.length;i++){
sum+=a[i]
}
}
getsum(1,2,3,4)
箭头函数
ES6标准新增了一种新的函数:Arrow Function(箭头函数)
1、如果函数的形参只有一个,那么就可以省略小括号
2、如果函数中只有一行代码,那么就可以省略大括号
//语法格式:let fn = (x) => {return x * x }
let fn=(x)=>{
return X * X
}
//函数中形参只有一个
let fn=Y=>{
return Y * Y
}
//函数中函数体只有一行代码
let fn=G=>return G+G
箭头函数的使用场景
//反复性定时器
window.setInterval(()=>{
console.log('定时器')
})
//变量数组
[1,2,3,4,5].forEach((item)=>{
console.log(item)
})
[1,2,3,4,5].forEach(item=>console.log(item))
箭头函数的使用注意点
箭头函数中的this
注意:箭头函数内部中没有this,这个this是使用的上级this得指向
箭头函数所在的作用域的this
特别注意:
1、如果涉及到this的情况,不建议使用箭头函数
2、箭头函数不存在声明,所以移动要先声明再使用
3、箭头函数中没有arguments对象,所以不可以使用arguments,可以使用剩余参数来代替arguments
<script>
let obj={
uname:'张三丰',
age:23,
fei:function(){
//指向的是上级作用域的位置
window.setInterval(()=>{
console.log(this)
},1000)
}
}
</script>
构造函数的封装
function Person(uname,age,sex,height,wight) {
this.uname=uname,
this.age=age,
this.sex=sex,
this.height=height,
this.wight=wight,
this.say=function (){
console.log('说话')
},
this.eat=function(){
console.log('吃饭')
}
}
//实例化
let o1= new Person('阿飞','33','男','188cm','88kg')
let o2= new Person('李四','44','女','160cm','50kg')