一、数组的应用
1.1-根据数组元素生成手风琴
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.box{
width: 1120px;
height: 260px;
margin: 50px auto;
display: flex;
overflow: hidden;
}
.box>div{
width: 120px;
border: 1px solid #fff;
transition: all 0.5s;
}
.box>div:hover{
width: 400px;
}
</style>
</head>
<body>
<!-- <div class="box">
<div><img src="./images/1.jpg" alt=""></div>
<div><img src="./images/2.jpg" alt=""></div>
<div><img src="./images/3.jpg" alt=""></div>
<div><img src="./images/4.jpg" alt=""></div>
<div><img src="./images/5.jpg" alt=""></div>
<div><img src="./images/6.jpg" alt=""></div>
<div><img src="./images/7.jpg" alt=""></div>
</div> -->
<script>
// 模拟后台返回的数据
let arr = [
'./images/1.jpg',
'./images/2.jpg',
'./images/3.jpg',
'./images/4.jpg',
'./images/5.jpg',
'./images/6.jpg',
'./images/7.jpg',
]
let str = '<div class="box">';
for(let i = 0; i < arr.length; i++){
str += `<div><img src="${arr[i]}" alt=""></div>`
}
str += '</div>'
document.write(str);
</script>
</body>
</html>
1.2-根据数组元素生成柱状图
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
<style>
.box {
width: 1000px;
height: 400px;
border-left: 1px solid #000;
border-bottom: 1px solid #000;
margin: 50px auto;
/* 父元素伸缩盒子 */
display: flex;
/* 水平方向均匀分布 */
justify-content: space-around;
/* 垂直方向底部对齐 */
align-items: flex-end;
}
.box > div {
width: 50px;
height: 100px;
background-color: pink;
text-align: center;
font-size: 14px;
/* 伸缩盒子 */
display: flex;
/* 修改伸缩盒子主轴为垂直方向 */
flex-direction: column;
/* 修改主轴方向两端对齐 */
justify-content: space-between;
}
.box > div span {
margin-top: -20px;
}
.box > div h3 {
margin-bottom: -40px;
}
</style>
</head>
<body>
<!-- <div class="box">
<div>
<span>50</span>
<h3>一季度</h3>
</div>
<div>
<span>50</span>
<h3>二季度</h3>
</div>
<div>
<span>50</span>
<h3>三季度</h3>
</div>
<div>
<span>50</span>
<h3>四季度</h3>
</div>
<div>
<span>50</span>
<h3>一季度</h3>
</div>
</div> -->
<script>
// 定义一个数组模拟后台返回的数据
//
let month = [100, 120, 230, 110, 300, 260, 130, 90, 300, 200, 150, 80];
let strHtml = '<div class="box">';
for(let i = 0; i < month.length; i++){
strHtml += `<div style="height: ${month[i]}px;">
<span>${month[i]}</span>
<h3>${i+1}月</h3>
</div>`
}
strHtml += '</div>'
document.write(strHtml);
</script>
</body>
</html>
1.3 求数组中的最大值
/*
擂台思想:
1. 先定义一个变量 max 将数组中的0号元素赋值给max
2. 从1号下标开始遍历数组
3. 将遍历 到的元素 与 max里的值进行比较
4. 如果 遍历到的元素 比 max里的大,就覆盖max里的值
*/
/* let arr = [20, 30, 8, 40, 12, 24, 15];
// 1. 先定义一个变量 max 将数组中的0号元素赋值给max
let max = arr[0]
// 2. 从1号下标开始遍历数组
for(let i=1; i<arr.length; i++){
// 3. 将遍历 到的元素 与 max里的值进行比较
if(arr[i] > max){
// 4. 如果 遍历到的元素 比 max里的大,就覆盖max里的值
max = arr[i]
}
}
console.log(max) */
1.4 数组的冒泡排序法
<script>
let arr = [9, 5, 3, 8, 17, 6];
// 外层循环控制找几次最大的
for(let j = 1; j < arr.length; j++){
// 内层:最大的放在最后面
// i 与 i+1 相邻的两个数比较
for(let i = 0; i < arr.length -j; i++){
// 如果前面的比后面的大,就交换位置
if (arr[i] > arr[i+1]){
let c = arr[i];
arr[i] = arr[i+1];
arr[i+1] = c;
}
}
}
console.log(arr);
</script>
二、函数类型
1.0-函数介绍
-
1.在实际开发中,我们有很多功能代码 并
不是只执行一次,而是需要在很多个地方。- 例如我们之前学习过的求和功能 :购物车页面需要求和,自己的订单列表页面需要求和查看总消费,还有待付款页面等等
- 多个地方:可以是同一个程序员好多个页面都需要使用。 也可以是不同程序员所负责的页面
-
2.那么既然是相同的功能代码,我们肯定不能复制粘贴去写冗余代码。这样万一功能有变化,维护起来就会很不方便
-
3.而函数就是解决这些重复功能的
代码复用问题- 函数是一个数据类型,可以理解为存储代码的容器。 把这些代码给存到变量中,要使用的时候取出来执行即可。
1.1-函数声明/调用
/* 需求:一段代码 需要在很多个地方使用 */
/*函数语法
1.声明函数 : 是一个存储过程,此时不会执行函数体代码
function 函数名(){
函数体代码: 需要存储的一段代码
}
2.调用函数 : 执行函数体代码
函数名()
*/
function nxn(){
let str = '<table width="800" height="500" border="1" rules="all">';
for(let col=1;col<5;col++){
str += '<tr>';
for(let row=1;row<= col;row++){
str += `<td>${row}*${col}=${row * col}</td>`;
}
str += '</tr>';
}
str += '</table>';
document.write(str)
}
// 函数的调用
// 函数定义的代码不会自动执行,必须人为的调用
// 语法:函数名()
//调用者A
nxn();
//调用者B
nxn();
1.2-函数参数
- 函数参数 : 调用者 传递数据 函数
- 传:调用者 ----函数名(实际参数)
- 收:函数 ----function 函数名(形式参数){ //函数体代码 }
- 函数传参本质: 实参给形参赋值的过程
- 函数传参是按照传入顺序一一赋值
- 函数每一次调用传参过程都是独立的,互不影响
- 函数 形参数量 和 实参数量 可以不一致的
<script>
/*
参数的作用是用于在调用函数是向函数内部传递数据
参数分形参与实参。
形参:
函数定义时的参数,
在函数内部就是一个变量
实参:
函数调用时的参数
实参与形参之间就是一个是传递一个是接收
*/
function getSum(v1,v2){
console.log(v1,v2)
}
let x = 10;
getSum(x,200); // 对10 与20 求和
getSum(30,50); // 对30 与50 求和
/*
形参 与 实参,共用作用将外部的数据传递到函数内部。
实参是传,形参是收
数据的传递是按顺序
形参只在内部有效
函数的参数就是将函数外部数据传递到函数内部进行运算。
*/
1.3 函数的参数细节
<script>
function fn(x,y,z,arr){
// console.log(x,y,z);
console.log(arr);
}
let a = 10;
fn(a, true, 'hello', [40,50,60,70]) // let arr = [40,50,60,70]
// console.log(x); // 尝试在函数外部访问形参,报错
/*
细节:
实参与形参之间是按顺序传递,
形参就是一个变量,只在函数内部访问
参数可以是任何类型
*/
</script>
1.4 函数形参实参个数匹配
<script>
// 函数形参实参个数匹配
function getSum(num1, num2) {
console.log(num1 + num2);
}
// 1. 如果实参的个数和形参的个数一致 则正常输出结果
getSum(1, 2);
// 2. 如果实参的个数多于形参的个数 会取到形参的个数
getSum(1, 2, 3);
// 3. 如果实参的个数小于形参的个数 多于的形参定义为undefined 最终的结果就是NaN
// 形参可以看做是不用声明的变量 num2 是一个变量但是没有接受值 结果就是undefined 在JavaScript种,形参的默认值是undefined。
getSum(1); // NaN
// 建议 我们尽量让实参的个数和形参相匹配
</script>
1.5 函数默认参数(逻辑短路运算)
<script>
/*
1.函数默认参数,我们自己在开发中使用不多。(了解后面很多js框架函数默认参数底层原理)
2.函数默认参数 使用 逻辑运算符短路运算(逻辑中断)
2.1 短路运算: 左边式子就可以决定结果,右边式子不执行
&& : 一假则假
|| : 一真则真
! : 取反(没有短路运算,因为只有一个式子)
2.2 短路规则:
&& : 找假。 左边式子值可以转成false,则无条件返回左边式子的值,右边不执行。 反之无条件返回右边式子的值。
|| : 找真。 左边式子值可以转成true,则无条件返回左边式子的值,右边不执行。 反之无条件返回右边式子的值。
*/
let res = undefined && 20
console.log( res )//undefined
let res1 = undefined || 20
console.log( res1 )//20
//需求:给函数添加默认参数0
// (1)如果用户有传递实参,就使用用户传递的实参
// (2)如果没有传,就使用默认参数
function getSum(num1,num2){
num1 = num1 || 0
num2 = num2 || 0
console.log(num1+num2)
}
getSum(66)
</script>
1.6 函数参数练习
/ 需求:封装一个函数,对任意数组求和
function getSum(data){
// console.log(data);
let sum = 0;
for(let i=0;i<data.length;i++){
sum += data[i]
}
// 这里的输出仅仅是为了验证代码正确,所以能log
console.log(sum)
}
let arr = [10,20,30,4];
getSum(arr)
getSum([4,2,7,4,10,29])
// 需求:封装一个函数,实例对任何一个数组求最大值。
function getMax(arr){
let max = arr[0]
for(let i = 0; i < arr.length; i++){
if(arr[i] > max){
max = arr[i];
}
}
console.log(max);
}
getMax([10,21,8,17,59,45,37]);
1.7 函数的返回值
函数返回值 : 函数 传递数据 给调用者
1. 传 : 函数
function 函数名(){ return 值 }
2. 收 : 调用者
let 变量名 = 函数名()
3. 注意点
(1)函数return关键字后面的代码不会执行的
* 只要有return关键字,函数体立即结束执行。
(2)如果函数没有return,则默认返回值是undefined
// 函数的返回值
// return 数据
// 函数内部return的数据会返回到函数的调用处
function fn(){
// 定义一个变量模拟函数内部生成的数据
let data = 200;
// 函数内部的数据可以在内部访问
console.log(data);
// 将data中的数据返回
return data;
}
// 外部要接收
let ret = fn();
console.log(ret)
1.8 return的特点
<script>
// 1. 函数内部只要遇到return就会中断函数的执行
// function fn(){
// console.log('hello')
// return 100;
// console.log('world')
// }
// fn();
// 2. 函数内部如果想返回多个数据,需要将多个数据组成数组
// function fn(){
// return [10, 20];
// }
// let ret = fn();
// console.log(ret)
// 3. 函数内部的return后可以不写数据,单纯只是为了中断函数的执行
function fn(){
// ....
// ....
// ....
return;
// ....
// ....
// ....
}
fn();
// 4. 函数的参数可以是任何类型,函数的返回值也可以是任何类型
</script>
1.9 arugments的使用
当我们不确定有多少个参数传递的时候,可以用arguments来获取,在JavaScript中,arguments实际上它是当前函数的一个内置对象。所有函数都内置了一个arguments对象,arguments对象中存储了传递的所有实参。
arguments展示形式是一个伪数组,因此可以进行遍历。伪数组具有以下特点:
- 具有length属性
- 按索引方式存储数据
- 不具有数组的push,pop等方法
// arguments 的使用 只有函数才有arguments对象 而且是每个函数都内置好了这个arguments
function fn(){
console.log(arguments); //里面存储了所有传递过来的实参
console.log(arguments.length); // 3
console.log(arguments[2]); //3
// 我们可以按照数组的方式遍历arguments
for(var i = 0; i < arguments.length; i++){
console.log(arguments[i]);
}
}
fn(1,2,3);
//伪数组 并不是真正意义上的数组
// 1.具有数组的length
// 2.按照索引的方式进行存储的
// 3.它没有真正数组的一些方法 pop() push() 等等
1.10 函数返回值练习
// 封装一个函数,对任意数组求最大值,并将最大值返回。
/* function getMax(data){ // data = arr
let max = data[0];
for(let i=1;i<data.length;i++){
if(data[i] > max){
max = data[i]
}
}
return max;
}
let arr = [5,20,19,28,23,17]
let ret = getMax(arr)
console.log(ret) */
<script>
// 封装一个函数,
// 功能:在一个数组中查找是否有某个元素存在,如果存则返回true,
/**
* @param1 array
* @param2 *
* @return boolean
*/
function find(arr,target){
// let arr = ['zhangsan','lisi','wangwu','zhaoliu','tianqi']
// let target = 'qq'
for(let i=0;i<arr.length;i++){
if(arr[i] == target){
return true;
}
}
}
let stus = ['zhangsan','lisi','wangwu','zhaoliu','tianqi'];
let na = 'lisi'
let ret = find(stus,na);
console.log(ret);
</script>
1.11 利用函数求任意个数的最大值
<script>
// 利用函数求任意个数的最大值
function getMax(){ //arguments = [1,2,3]
var max = arguments[0];
for(var i = 1; i < arguments.length; i++) {
if (arguments[i] > max) {
max = arguments[i];
}
}
return max;
}
console.log(getMax(1,2,3)); // 3
console.log(getMax(1,2,3,4,5)); //5
console.log(getMax(11,2,34,444,5,100)); //444
</script>
1.12 函数是可以相互调用的
<script>
// 函数是可以相互调用的
function fn1(){
console.log(11);
fn2(); // 在fn1 函数里面调用了 fn2 函数
}
fn1();
function fn2() {
console.log(22);
}
</script>
1.13 利用函数判断闰年
<script>
// 用户输入年份,输出当前年份2月的天数
function backDay() {
var year = prompt('请您输入年份:');
if() { // 调用函数需要加小括号
alert('当前年份是闰年2月份有29天');
} else {
alert('当前年份是平年2月份有28天');
}
}
backDay();
// 判断是否是闰年的函数
function isRunYear(year) {
// 如果是闰年我们返回 true 否则 返回false
var flag = false;
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
flag = true;
}
return flag;
}
</script>
1.14 函数的两种声明方式
<script>
// 函数的2种声明方式
// 1.利用函数关键字自定义函数(命名函数)
function fn() {
console.log('我是函数')
}
fn();
// 2.函数表达式(匿名函数)
// var 变量名 = function() {};
var fun = function(aru) {
console.log('我是函数表达式'); // 我是函数表达式
console.log(aru); // hahaha
}
fun('hahaha');
// (1) fun是变量名 不是函数名
// (2) 函数表达式声明方式跟声明变量差不多,只不过变量里面存的是值 而 函数表达式里面存的是函数
// (3) 函数表达式也可以进行传递参数
</script>
1.15 匿名函数
<script>
// 具名函数,如下代码,函数的名称就是test
// function test() {}
// 函数名称() >> test()
// 匿名函数不能单独存在,它只有三个使用方式
// function (){} // 报错》》需要一个标识符
// 1.做为一个变量的值,值的类型是一个函数 -- 函数表达式
let age = 20
let fn = function() {
console.log(123)
}
fn()
// 2.做为一个自调用函数==立即执行的函数
;(function() {
console.log(123)
})()
// 3.将匿名函数做为函数的参数--回调函数
let btn = document.querySelector('button') // 获取元素
// 为btn这个元素添加一个事件监听器,添加一个单击事件的监听,当用户真的单击这个按钮的时候,调用你所传入的处理函数
btn.addEventListener('click', function() {})
let aaabbb123 = function() {
console.log('abc')
}
console.log(window)
1.16 利用函数转换时间案例
- 需求: 用户输入秒数,可以自动转换为时分秒
- 分析:
- ①: 用户输入总秒数
- ②:计算时分秒(封装函数) 里面包含数字补0
- ③:打印输出
- 计算公式:计算时分秒
- 小时: h = parseInt(总秒数 / 60 / 60 % 24)
- 分钟: m = parseInt(总秒数 / 60 % 60 )
- 秒数: s = parseInt(总秒数 % 60)
<script>
function getTime(miao) {
// 获取时
let hour = parseInt(num / 3600);
// console.log(hour);
// 获取分
let minute = parseInt(num % 3600 / 60);
// console.log(minute);
// 获取秒
let second = num % 60;
// console.log(second);
return [hour, minute, second];
}
let num = +prompt('请输入秒数'); // 3700
let time = getTime(num);
console.log(time); // [1, 1, 40]
document.write(`${num}秒的时间是${time[0]}时${time[1]}分${time[2]}秒`);
</script>
三、作用域
1.1-作用域介绍
- 注意:如果一个变量在声明的时候没有使用关键字。 例如:
num = 10,此时这个变量无论写在哪里都是全局变量。 (切忌:这是非常不规范的,千万不要这么写,否则以后代码可能会出现bug)
<script>
js变量作用域: 变量可以使用的区域
* 作用:避免变量污染(变量名相同导致代码冲突)
// 在JS中作用域可以全为三种:
// 全局: 在函数之外就是全局
// 全局变量:在全局定义的变量就是全局变量
// 局部:在函数内部就是局部
// 局部变量:在局部定义的变量就是局部变量
// 块级:只要语法中具有{}都是块级作用域
</script>
<script>
// 全局变量
let a = 10;
function fn(){
// 局部变量
let b = 20;
}
</script>
1.2 变量的访问范围
<script>
// 全局变量:访问不受限制
// 局部变量:局部变量只能在定义的函数内访问
// 全局变量
let a = 10;
function fn(){
// 局部变量
let b = 20;
// 尝试在局部访问全局变量a
// console.log(a);
// console.log(b);
}
fn();
// 尝试在全局访问局部变量b
console.log(b); // 报名无法访问
// console.log(a);
</script>
1.3 块级作用域-专题
<script>
// 只要语法中具有{}都会形成一个块级作用域
// 块级作用域只影响let声明的变量
// var 也是用于声明变量。
// let a = 10;
// var b = [10,20];
// console.log(a,b);
// var与let的区别,主要体现在块级作用域上
// {
// var y = 20;
// let x = 10;
// }
// console.log(y); // 20
// console.log(x); // 报错
// console.log(n);
// var n = 20;
// let m = 10;
// console.log(m);
// let声明的变量必须先定义后使用
// 不推荐直接为变量赋值的方式定义变量,推荐使用let
age = 20;
console.log(age);
/*
小结:
let声明受块级作用域限制
var也是用于声明变量的,var声明的变量不受块级作用域限制。
*/
</script>
1.4 作用域链以及链式查找
<script>
// 作用域链:由嵌套的作用域形成的一个链条。
// 链式查找:当在某个作用域内使用一个变量时,如果这个变量不存在,由会向上一级作用域找
// 作用域链: 默认情况下,代码处于全局作用域(0级链),当声明一个函数之后就会开辟一个局部作用域(1级),而函数里面又可以声明一个函数,又会形成新的作用域(2级),以此类推形成的结构称之为作用域链
// 变量访问规则: 就近原则
* 当你在一个作用域访问变量的之后,首先会看当前作用域有没有声明。如果有则访问。 没有则往上级作用域查找,有没有声明。有则访问,没有则继续往上。直到作用域最顶端0级,如果还没有找到。则程序报错 xxx is not defined
</script>
<script>
// let a = 10
function fn(){
// let a = 100
function fn1(){
let a = 1000
function fn2(){
console.log(a); // 1000
}
fn2();
}
fn1()
}
fn();
</script>