文章目录
- 函数
- 基本使用
- 函数提升
- 函数参数
- arguments对象(了解)
- 剩余参数(重点)
- 展开运算符(...)
- 逻辑中断
- 函数参数-默认参数
- 函数返回值-return
- 作用域(scope)
- 全局作用域
- 局部作用域
- 变量的访问原则
- 垃圾回收机制
- 闭包
- 匿名函数
- 函数表达式
- 立即执行函数
- 箭头函数
- 箭头函数中的 this (重要)
- ES6对象简写
- 断点调试-进入函数内部
函数
- 函数:是可以被重复使用的代码块。
- 作用:函数可以把具有相同或相似逻辑的代码封装起来,有利于代码复用。
基本使用
-
定义函数(声明函数):function
-
调用函数:定义一个函数并不会自动执行它,需要调用函数。
//声明函数 function 函数名() {函数体 } //调用函数 函数名()//需求:封装一个函数,计算两个数的和 function getSum() {let num1 = 1let num2 = 9console.log(num1 + num2) } getSum()//需求: 封装函数,计算1~100之间的累加和 function getSum100() {let sum = 0for (let i = 1; i <= 100; i++) {sum += i}console.log(sum) } getSum100()
函数提升
- 说明:
- 函数提升:提升到当前作用域最前面;
- 只提升声明,不提升调用;
- 函数表达式不存在提升的现象,表达式相当于变量;
- 函数提升能够使函数的声明调用更灵活
函数参数
- 形参:声明函数时小括号里的叫形参。
- 实参:调用函数时小括号里的叫实参。
- 执行过程:把实参的数据传递给形参,提供给函数内部使用。
function getSum(x,y) {console.log(x,y) //3 5return x + y
}
let res = getSum(3,5)
console.log(res) //8
注意:在js中,形参和实参的个数可以不一致。形参过多会自动填上undefined;实参过多,会忽略多余的实参。
建议:开发中保持形参和实参的个数一致。
arguments对象(了解)
-
arguments:是函数内部内置的伪数组变量,它包含了调用函数时传入的所有实参,但只存在于函数,外面无法使用。
-
作用:动态获取函数的实参。
-
可以通过for循环依次得到传递过来的实参。
剩余参数(重点)
-
剩余参数: 允许我们将一个不定数量的参数表示为一个数组.
简单理解:用于获取多余的实参,并形成一个真数组
-
**使用场景:**可以解决形参和实参个数不匹配的问题
<body><script>function fn(a, b, ...c) {//剩余参数只能写在参数的最后面console.log(a + b, c) //c:真数据(数组)}fn(1, 2, 3, 4, 5)</script>
</body>
- 剩余参数和 arguments 区别:
...
是语法符号,置于最末函数形参之前,用于获取多余的实参- 借助 … 获取的剩余实参,是个真数组
- 箭头函数不支持arguments,但是可以使用剩余参数
- 开发中,还是提倡多使用 剩余参数
展开运算符(…)
- 展开运算符:将一个数组/对象进行展开
<body><script>//展开运算符 // 数组const arr = [1, 2, 3]console.log(...arr)// 对象const obj = {uname: 'niuniu',age: 18}console.log({...obj})// 应用:数组的展开,求最大值console.log(Math.max(1, 2, 3, 9))console.log(Math.max(...arr))// 合并数组const arr1 = [4, 5, 6]const arr2 = ['haha', 'lala', 'xixixi']const arr3 = [...arr1, ...arr2]console.log(arr3)// 合并对象const obj1 = {uname: 'niuniu'}const obj2 = {age: 18}const obj3 = {...obj1,...obj2}console.log(obj3)</script>
</body>
逻辑中断
-
逻辑中断:存在于逻辑运算符 && 和 || 中,左边如果满足一定条件会中断代码执行,也称为逻辑短路。
-
作用:解决参数形参传递的问题
-
解释:
function getSum(x,y) {//逻辑中断:如果 实参 没有传递给形参 x 和 y ,则会返回 0,而不是NaNx = x || 0y = y || 0console.log(x,y)
}
getSum(2) //2 0 => 如果没有逻辑中断,则返回 NaN
getSum(3,6) //3 6
函数参数-默认参数
-
默认参数:可以给形参设置默认值。
-
说明:默认值只会在 缺少实参传递 或 实参为undefined 才会被执行。
-
作用:解决参数形参传递的问题。
-
与逻辑中断的区别:
-
默认参数主要处理函数形参,比逻辑中断简单;
-
逻辑中断除了参数,还可以处理更多的需求,例如,
-
function getSum(x = 0,y = 0) {console.log(x,y)
}
getSum(4,1) //4 1
getSum(4) //4 0
函数返回值-return
- 返回值:把处理结果返回给调用者。
- 注意:
- 结束函数:return 会立即结束当前函数,后面的代码不会被执行。
- 不要换行:在return关键字和被返回的表达式之间不允许使用换行符,否则自动补充分号。
- 默认返回:可以没有return,这时默认返回值为undefined。
作用域(scope)
-
作用域:变量或者值在代码中可用性的范围.
-
作用:提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突。
全局作用域
- 作用于所有代码执行的环境(整个script标签内部)或者一个独立的 js文件。
- 变量:全局变量
- 全局变量 在任何区域都可以访问和修改。
局部作用域
- 函数作用域:作用于函数内部的代码环境。
- 块级作用域:{} 大括号内部。
- 变量:局部变量
- 局部变量 只能在当前局部内部访问和修改。
注意:
- 如果函数内部,变量没有声明,直接赋值,也当全局变量看,但是强烈不推荐
- 但是有一种情况,函数内部的形参可以看做是局部变量。
变量的访问原则
- 访问原则:在能够访问的情况下 先局部,局部没有 再找全局,总结:
就近原则
//练习1
function f1 () {let num = 123function f2 () {console.log(num) //123}f2()
}
let num = 234
f1()// 练习2.
let a = 1
function fn1() {let a = 2let b = '22'fn2()function fn2() {let a = 3fn3()function fn3() {let a = 4console.log(a) //4console.log(b) //'22'}}
}
fn1()
垃圾回收机制
- 垃圾回收机制(Garbage Collection),简称 GC
- JS中内存的分配和回收都是自动完成的,内存在不使用的时候会被垃圾回收器自动回收。
- js环境种内存的生命周期:
- 内存分配:当我们声明变量、函数、对象的时候,系统会自动为他们分配内存。
- 内存使用:即读写内存,也就是使用变量、函数等。
- 内存回收:使用完毕,由垃圾回收器自动回收不再使用的内存。
- 说明:
- 全局变量一般不会回收(关闭页面回收)
- 一般情况下局部变量的值, 不用了, 会被自动回收掉
- **内存泄漏:**程序中分配的内存由于某种原因程序未释放或无法释放叫做内存泄漏。
闭包
- 概念:一个函数对周围状态的引用捆绑在一起,闭包让开发者可以从内部函数访问外部函数的作用域。
简单理解:闭包 = 内层函数 + 外层函数的变量
- 作用:实现数据的私有,避免全局污染,外层函数有可以访问里层函数变量。
- 问题:内存泄漏
<body><script>// 闭包 : 内层函数 + 外层函数的变量// function outer() {// let a = 1// function f() {// console.log(a)// }// f()// }// outer()// 案例:统计函数的调用次数function fn() {let count = 0function fun() {count++console.log(`fn函数调用了${count}次`)}return fun}const f = fn()f()</script>
</body>
匿名函数
函数表达式
-
函数表达式:将匿名函数赋值给一个变量,并且通过变量名称进行调用。
-
使用场景:后期web api 阶段会使用。
-
注意:
- 函数也是一种数据类型;
- 函数表达式必须先定义,后使用;
-
语法:
//定义 let fn = function () {//函数体 }//调用 fn()
立即执行函数
-
场景介绍:避免全局变量之间的渲染。
-
语法:
//方法1 (匿名函数)();//方法2 (匿名函数());//方法1 (function () {console.log('niuniu') })();//方法2 (function () {console.log('zhuzhu') }());
注意:多个立即执行函数要用 ; 隔开,前后都要,否则会报错。
箭头函数
- 箭头函数比函数表达式更简洁的一种写法
- 使用场景:箭头函数更适用于那些本来需要匿名函数的地方,写法更简单
- 用法细节:
- 当箭头函数只有一个参数时,可以省略参数的小括号,其余个数不能省略(没有参数也需要写小括号)
- 当箭头函数的函数体只有一句代码 可以省略函数体大括号,这句代码就是返回值(可以不用写return)
- 如果返回的是个对象,则需要把对象用小括号包裹
- 箭头函数里面没有arguments,但是有剩余参数
<body><script>//箭头函数 基本写法// const fn = () => // console.log('我是箭头函数')// }// fn()// 细节写法// const fn = a => console.log(a)// fn(1)// const fn = a => a// const res = fn('niuniu')// console.log(res)// const fn = () => {// const obj = {// uname: 'niuniu',// age: 18// }// return obj// }// const res = fn()// console.log(fn())// const fn = () => ({uname: 'niuniu', age: 18})// const res = fn()// console.log(res)const fn = (...arr) => {console.log(arr)}fn(1, 2, 3)</script>
</body>
箭头函数中的 this (重要)
以前函数中的this指向是根据如何调用来确定的。简单理解就是this指向调用者
箭头函数本身没有this,它只会沿用**上一层作用域的this **。
<body><button>按钮</button><script>//箭头函数的 this问题const btn = document.querySelector('button')// btn.addEventListener('click', () => {// console.log(this) //箭头函数里的this是指向上一级作用域// })//定时器中使用,事件源,推荐使用箭头函数//需求:点击按钮禁用,三秒后启用btn.addEventListener('click', function () {btn.disabled = truesetTimeout(() => {console.log(this)btn.disabled = false}, 3000)})</script>
</body>
注意:在开发中【使用箭头函数前需要考虑函数中 this 的值】
- 事件回调函数使用箭头函数时,this 为全局的 window,不太推荐使用箭头函
- 定时器里面的如果需要this,可以使用箭头函数
ES6对象简写
-
在对象中,如果属性名和属性值一致,可以简写只写属性名即可。
-
在对象中,方法(函数)可以简写
<body><script>// ES6对象属性和方法的简写const uname = 'niuniu'const age = 18// 对象属性const obj = {// uname: uname,// age: ageuname,age,// 方法简写sing() {console.log('hahahaha')}}console.log(obj)obj.sing()</script> </body>
断点调试-进入函数内部
-
F11 可以进入函数内部调试
-
可以使用监视,来看数组的变化。