函数
-
存储一段代码
-
定义(声明)
function 函数名(a, b){ /* var a var b a = 1 b = 2 */ // 一段代码 } -
调用(执行)
- 函数名(1,2)
-
函数的优点
- 复用
- 维护
-
函数参数
- 含义
- 形参: 其实就是在函数内部声明一个变量
- 实参: 其实就是给形参赋值
- 个数关系
-
返回值
- 含义:函数执行之后得到结果
- 有没有返回值?
- 看函数体内有没有写return 值
- 默认函数返回值undefined
- 什么时候使用?
- 一般函数调用之后,需要得到函数执行的结果 这个结果用于下一步运算或者判断
-
return
- 返回值
- 终止函数的执行
函数定义方式
- 声明式定义
function 函数名(){ // 一段代码 } - 赋值式定义
var 函数名 = function(){ // 一段代码 }
预解析、预编译
- 正常我们写完的js直接打开浏览器就能够运行,运行之后就能看到运行的结果
- 浏览在运行js之前会提前将整个js的代码通读,会挑出重点的内容提前执行,这个过程就是预解析的过程
- 重点
- var声明的变量会提前声明
- 声明式函数会提前定义
- 影响
- var声明的变量可以提前使用但是他的值undefined,因为只会将定义提前,不会将赋值提前
- 声明式的函数可以在定义之前调用
作用域
- 含义: 一个变量或者函数起作用的范围
- 分类:
- 全局作用域: 不被任何一个函数包裹的区域就称为全局作用域
- 局部作用域: 被一个函数所包裹的区域就称为局部作用域
- 变量分类
- 全局变量: 在全局作用域定义的变量称为全局变量
- 全局变量可以在全局使用,也可以在局部使用
- 局部变量: 在局部作用域定义的变量称为局部变量
- 局部变量只能在当前自己的局部使用,无法在全局或者其他的局部使用
- 全局变量: 在全局作用域定义的变量称为全局变量
作用域的访问(就近、往上)
- 在使用变量的时候遵循的原则
- js在使用一个变量的时候 会优先在自身作用域里面查找,如果自身有就使用自身
- 如果自身没有往上一级作用域查找,上一级有就使用上一级的
- 上一级没有就在往上上一级,一直找到全局作用域,如果全局有就使用全局,全局没有就会报错
作用域的赋值
-
在给一个变量赋值的时候遵循的原则
-
js在给一个变量赋值的时候 会优先看当前自身的作用域有没有定义 如果有就给当前自身的作用域变量赋值,不会往上赋值了
-
如果自身没有定义,会往上一级查找,看上一级作用域里面有没有定义这个变量,如果上一级有定义,就给上一级作用域里面的变量赋值
-
如果上一级没有定义,再往上上一级查找,一直找到全局作用域,如果全局作用域里面有定义,就给全局作用域里面变量赋值,全局没有定义,会自动在全局声明一个变量,然后给这个变量赋值。
-
特殊函数
-
匿名函数: 将一个函数当成一个数据赋值给某一个变量
- 事件处理函数多为一个匿名函数
function(){ } -
自执行函数:在函数定义的时候就会自动调用函数
- 将一段封装在一个函数内部 封装的时候需要立即执行这段代码
(function(){ // 此处代码在定义的位置就会执行 })() (function getSum(){ // 此处代码在定义的位置就会执行 })() -
递归函数(js的重难点)
- 函数在内部调用自己
- 抛出错误
Maximum call stack size exceeded - 递归有两个过程,第一个就是传递的过程,第二个返回的过程
- 传递的过程中,没有得到结果的函数会在call stack(调用栈)等待
- 返回的过程中,得到结果的函数就在一个一个出栈
-
递归优点
- 可以解决循环不能解决的问题
-
递归缺点
- 每一次递归都会导致函数在call stack等待,如果等待的函数超出了call stack的最大长度 就会报错
-
递归使用场景
- 对象深克隆
- 遍历dom
-
数组(Array)
- js中最重要的数据类型
- 数组是一种复杂数据类型
- 数组是一个有序的数据集合,有序是体现在下标(索引)上面
- 往数组里面放一个数据,自动生成一个下标,从0开始
- 数组创建
- 字面量方式
- var 变量名 = []
- 内置构造函数方式
- var 变量名 = new Array()
- 字面量方式
- 如何往数组里面添加数据
- 可以通过下标
- 数组名[下标] = 数据
- 可以通过方法来添加
- 数组名.push(数据)
- 数组名.unshift(数据)
- 可以通过下标
- 如何获取数组的长度
- 数组名.length
- 如何取出数组里面的数据
- 下标法
- 下标的范围 [0 - 数组长度-1]
- 数组名[下标]
- 越界访问 不会报错 得到的是undefined
- 通过方法获取数据
- 数组.pop() 取出数组的最后一位
- 数组.shift() 取出数组的第一位
- 会改变数组的长度
- 下标法
实例
(以下代码均为课程实例)
(1)函数的两种定义方式
<script>
/*
声明式
可以在定义之前和定义之后使用
*/
getSum();
function getSum() {
console.log("求和函数");
}
getSum();
/*
赋值式
只能在定义之后使用
*/
getSum01()
var getSum01 = function () {
console.log("求和函数01");
};
getSum01();
</script>
(2)作用域
<script>
// a是在全局定义的
var a = 1
function foo(){
// b是在函数内部定义的
var b = 2
// 变量a可以在函数内部使用
console.log(a) // 1
// 变量b可以在函数内部使用
console.log(b) // 2
}
foo()
// 变量a也可以在函数外部(全局)使用
console.log(a) // 1
// 变量b在函数外部无法使用
console.log(b) // b is not defined
</script>
(3)作用域误区
<script>
/*
相当于自动在全局 var b
给这个变量赋值 b = 1
*/
function foo(){
b = 1 // 只是给b赋值了 没有定义b 所以b不是局部变量
console.log(b)
}
foo()
console.log(b)
</script>
(4)作用域的赋值原则
<script>
// var a = 1
function foo(){
// var a = 2
function baz(){
// var a = 3
a = 4 // 给变量a重新赋值
console.log(a) // 4
}
// console.log(a) // 1
baz() // 只有在调用baz之后a才会变化
console.log(a) // 4
}
foo()
console.log(a) // 4
</script>
(5)使用递归求10!
<script>
// 累计去乘
// 10! = 10 * 9 * 8 *...*3*2*1
// jieCheng(10) = jieCheng(9) * 10
// jieCheng(9) = jieCheng(8) * 9
// jieCheng(8) = jieCheng(7) * 8
// jieCheng(7) = jieCheng(6) * 7
// ...
// jieCheng(2) = jieCheng(1) * 2
// jieCheng(1) = 1
function jieCheng(n){
// 递归必须要有结束条件 否则就会出现死递归
if(n === 1){
return 1
}
debugger // 相当在这个打一个断点 程序每一次运行到这个地方的时候都会停止一下
return jieCheng(n-1) * n
}
console.log(jieCheng(1000000))
</script>
(6)求斐波那契数列的第n项
<script>
function fb(n){
// 一般递归先写结束条件
if(n==1 || n==2){
return 1
}
debugger
return fb(n-1) + fb(n-2)
}
// fb(10)=fb(9) + fb(8)
// fb(9)=fb(8) + fb(7)
// fb(8)=fb(7) + fb(6)
// fb(7)=fb(6) + fb(5)
// fb(6)=fb(5) + fb(4)
// fb(5)=fb(4) + fb(3)
// fb(3)=fb(2) + fb(1)
console.log(fb(1))
console.log(fb(2))
console.log(fb(10))
</script>
(7)求最大公约数
<script>
/*
公约数
约数 倍数
最大公约数
算法: 拿大数除以小数 判断余数 如果余数为0 那么小数就是他们的最大公约数
不为0 继续拿小数除以余数 一直算到余数为0
10 1 2 5 10
12 1 2 3 4 6 12
10 5 0
12 10 2
10 2 0
20 8 4
8 4 0
25 15 10
15 10 5
10 5 0
*/
function gys(m,n){
// 判断m和n的大小 如果m>n交换位置
if(m>n){
var temp = null
temp = m
m = n
n = temp
}
// m一定比n小
var yu = n%m
if(yu==0){
// 如果余数为0 那么小数就是他们的最大公约数
return m
}
// 到这个代表 n除以m余数不为0
// 继续拿小数除以余数
return gys(yu, m)
}
console.log(gys(10,5)) // 5
console.log(gys(25,15)) // 5
console.log(gys(15,25)) // 5
</script>
(8)录入成绩的系统
<script>
// 定义一个数组存储成绩
var scoreList = []
// 录入6个同学
for(var i=1;i<=6;i++){
// 提示用户输入
var score = prompt('请输入成绩')
// 输一个录一个
scoreList.push(score)
}
console.log(scoreList)
</script>
(9)生成四位随机的验证码 0000 - 9999 放到数组里面
<script>
// 生成四位随机的验证码 0000 - 9999 放到数组里面
// function suiji(m, n) {
// return (parseInt(Math.random() * (n - m + 1)) + m)
// }
// var a = suiji(0000, 9999)
// console.log(a)
// var shuzu = []
// shuzu[0]=a
// console.log(shuzu)
// var a = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
// var code = "";
// for (var i = 0; i < 4; i++) {
// //0-1的随机小数 --> 0~数组长度-1的范围 取整
// var randPosition = Math.floor(Math.random() * (a.length - 1)); //每次生成一个随机数的位置
// code += a[randPosition];//带有随机位置作为下标,指示到当前随机产生的某个字符上,
// }
// alert(code);
// while (1) {
// var ss = prompt("请输入验证码");
// if (ss == code) {
// alert("输入正确");
// break;
// }
// else {
// alert("输入错误");
// }
// }
// 生成四位随机的验证码 0000 - 9999 放到数组里面
// var arr=[]
// arr.push(String(parseInt(Math.random()*10))+String(parseInt(Math.random()*10))+String(parseInt(Math.random()*10))+String(parseInt(Math.random()*10)))
// console.log(arr)
var str = []
for (var i= 1; i <= 4; i++) {
str.push(parseInt(Math.random() * 10))
}
console.log(str)
</script>
(10)生成四位不重复随机的验证码 0000 - 9999 放到数组里面
<script>
// 生成四位不重复随机的验证码 0000 - 9999 放到数组里面
var str = []
for (var i = 1; i <= 4; i++) {
var n = Math.floor(Math.random() * 10)
if (str.indexOf(n) === -1) { //str.indexOf(n)识别是否和n一样的字符,如果无 则输出-1
str.push(n)
} else {
i--
}
}
console.log(str)
</script>
(11)定义一个数组存储成绩,录入6个同学, 提示用户输入,输一个录一个, 求出输入的平均数
<script>
// 定义一个数组存储成绩
var scoreList = []
// 录入6个同学
for (var i = 1; i <= 6; i++) {
// 提示用户输入
var score = prompt('请输入成绩')
// 输一个录一个
scoreList.push(score)
}
console.log(scoreList)
// 求出输入的平均数
function avg(array) {//封装求平均值函数
var sum = 0;
for (var i = 0; i <= 6; i++) {
sum += array[i];
}
return sum/6;
}
console.log(avg(scoreList));
</script>