个人自学前端11-JS4-数组和循环

目录

数组和循环

数组入门和循环

一 数组入门

数组用于存储一组相关数据。作用和对象类似。

数组是有序的数据结构。

对象是无序的数据结构。

1.1:数组的相关概念

数组的创建,分两种方式:

1:直接量

2:构造函数

// 直接量
let arr = [1,2,3];
// 构造函数
let arr = new Array(1,2,3);

数组内的每个数据叫做数组的元素。或者叫做数组的数据项,每一项。(和html的元素不是一个意思)

可以通过元素的下标访问数组元素。(下标相当于门牌号)(对象通过属性名访问属性值)

数组的元素下标默认从0开始。

数组的长度(元素个数)可以通过length获取。

如果访问一个不存在的元素,得到undefined。(访问不存在的对象属性也是undefined)

// '班长','学委','体委'是数组的元素,对应的下标是0,1,2
let arr = ['班长','学委','体委'];
// 访问第一个元素
console.log(arr[0]);
// 访问第二个元素
console.log(arr[1]);
// 访问最后一个元素
console.log(arr[arr.length-1])
// 访问第101个元素,不存在,得到undefined
console.log(arr[100])
// 访问数组的长度。
console.log(arr.length)

1.2:数组的增删改查

1.2.1: 增加元素

可以通过没被占用的下标添加新元素

let arr=[1,2,3];
// 下标3没被占用,为数组添加了第四个元素4
arr[3] = 4;
// 如果添加第6个元素,则第5个元素是空的。
arr[5] = 6;
console.log(arr[4]);//undefined
1.2.2:删除元素

可以通过length=0来删除所有元素。删除指定元素后期学。

// 删除所有元素
let arr=[1,2,3];
arr.length = 0;
1.2.3:修改元素

通过已经被占用的下标修改元素

// 把第一个元素从1修改为100
let arr=[1,2,3];
arr[0] = 100;
1.2.4:查找元素

通过下标查找元素,如果元素不存在,得到undefined

下标从0开始,依次增加1.

let arr=[1,2,3];
console.log(arr[0]);//1
console.log(arr[10]);//undefined

1.3:数组常见格式

数组内元素的数据类型一般是,number,string,array和object

// 很简单的数组,元素类型分别是number和string
let arr = [1,2,3];
let arr = ['你','我','它'];
// 元素数据类型不一致也可以
let arr = [1,'你',true]
1.3.1:多维数组

数组的元素又是数组,称之为多维数组,常见二维数组,三维数组。

// 二维数组,arr的元素都是数组,分别是[1,2]和[2,4];
let arr = [[1,2],[3,4]];
// 打印arr的第一个元素.
console.log(arr[0]);//[1,2]
// 打印arr的第一个元素的第一个元素.
console.log(arr[0][0]);//1
1.3.2:对象数组

数组的元素是对象,称为对象数组。

// 数组的元素是对象,分别是{name:'幂幂'}和{name:'超越'}
let arr = [{name:'幂幂'},{name:'超越'}];
// 访问数组第一个元素.
console.log(arr[0]);//{name:'幂幂'}
// 访问数组第一个元素的name属性.
console.log(arr[0].name);//幂幂

二 获取元素进阶

获取元素可以通过id获取到一个元素,如果有10个元素,获取10次肯定是很麻烦的。

可以通过以下方法一次性获取多个元素,这时获取到的不是html标签,而是装着html标签的数组!

2.1:在页面中查找所有符合条件的标签

以下方法在document内查找所有符合条件的标签。

// 获取页面中所有的div元素, aDiv是数组!
let aDiv = document.getElementsByTagName('div');
// 获取页面中所有类名为active的元素,aDiv是数组!
let aDiv = document.getElementsByClassName('active');
// 获取页面中选择器为div.active的所有元素,aDiv是数组!
let aDiv = document.querySelectorAll('div.active');

通过以上方法获取到的是数组,可以通过数组下标来操作html标签:

// 通过标签名获取元素, aDiv是数组!
let aDiv = document.getElementsByTagName(元素标签名);
// 通过数组下标来设置第一个div的背景色
aDiv[0].style.background = 'red'

不管元素有多少个,通过以上方法获取的永远是一个数组,不是html标签!

通过以上方法获取元素,一定记得加下标!

// 通过标签名获取body。
let aBody = document.getElementsByTagName('body');
// 错,aBody是数组,不是标签
aBody.style.background = 'red';
// 正确,只能通过数组aBody的下标来获取body标签。
aBody[0].style.background = 'red';

2.2:在指定元素内查找所有符合条件的标签。

以下方法在指定的#wrap内获取符合条件的所有标签。

let oWrap = document.getElementById('wrap');
// 获取oWrap中所有的div子孙元素
let aDiv = oWrap.getElementsByTagName('div');
// 获取oWrap中所有类名为active的子孙元素
let aDiv = oWrap.getElementsByClassName('active');
// 获取oWrap中所有选择器为div.active的子孙元素
let aDiv = oWrap.querySelectorAll('div.active');
// 获取oWrap的所有子元素。(不获取孙子元素,不区分标签)
let aDiv = oWrap.children

难点:

querySelectorAll和getElementsByTagName以及getElementsByClassName的区别:

querySelectorAll是静态获取元素,一旦获取,length不会随着标签的增删而发生变化。

getElementsByTagName以及getElementsByClassName是动态获取,length会随着元素增删而变化。

PS:利用JS数组获取页面元素,只是一种映射,无法通过删除JS数组中的元素来实现在页面上删除标签

三 控制结构--循环

js 有两种控制结构,循环和判断。

循环用于处理逻辑相同的 js 操作。便于书写和批量处理。

// 相同的操作,如果需要执行多次,只能书写多次,这样很麻烦,维护也麻烦
console.log(100);
console.log(100);
console.log(100);
console.log(100);
console.log(100);

// 书写一个执行5次的循环,执行相同的操作。这样更简单
for(let i=0;i<5;i++){
    console.log(100);
}

语法:

// 当表达式2返回值为false,则循环终止
for(表达式1;表达式2;表达式3){
	循环体代码
}

表达式2永远不为false,则循环永远无法停止,这种循环称之为死循环。

难点:

1:怎么写。

写循环,其实就是在教浏览器数数。i 就是计数变量。至于从几开始数,怎么数,数到几,都可以设置。

let i = 0;表示从0开始数,i<5表示数到5就停,i++,表示每次数数加1。

自然可以从任何数开始数,数到任何数就停,每次数数可以加任何数减任何数。

// 从-1开始数,数数不超过4,每次数数+2
for(let i=-1;i<=4;i+=2){
	循环体代码
}

2:循环执行顺序

循环执行顺序:

表达式1>表达式2判断>循环体代码>表达式3>表达式2判断.......直到表达式2返回false,则终止循环.

//顺序:
//1:let i = 0;
//2:i<5,判断i<5的返回值是否为true,如果是,执行第3步,否则终止循环
//3:console.log(100);执行循环代码体;
//4:i++,i的值+1
//5:i<5,判断i<5的返回值是否为true,如果是,执行第6步,否则终止循环
//..............直到i<5返回false.
for(let i=0;i<5;i++){
    console.log(100);
}

知道了顺序,就可以看懂任何循环代码.

3:如何看懂循环在做什么

看懂代码,需要注意两件事情:

1:循环多少次。

2:循环体代码是什么。

// 1:这个循环循环3次
// 2:循环体代码是判断
// if(true){
//	 console.log(1000)
// }
for(let i=0;i<3;i++){
	if(true){
		console.log(1000)
	}
}
// 因此以上循环代码的意思是:
// 执行3次判断
// if(true){
//    console.log(1000)
// }
// -------------------------------------------------------------------------
// 1: 这个循环循环5次
// 2:循环体代码是添加事件oBtn.onclick = function(){console.log(10000)}
for(let i=0;i<=4;i++){
	oBtn.onclick = function(){console.log(10000)}
}
// 因此以上循环代码的意思是:
// 执行5次添加事件。即执行三次oBtn.onclick = function(){console.log(10000)}
// --------------------------------------------------------------------------
// 1:这个循环循环5次
// 2:循环代码体又是一个循环
// for(let j=0;j<5;j++){
//    console.log(100);
// }
for(let i=0;i<=4;i++){
	for(let j=0;j<5;j++){
        console.log(100);
    }
}
// 因此以上循环代码的意思是:
// 执行5次内部循环
// for(let j=0;j<5;j++){
//    console.log(100);
// }
// 内部循环的意思的分析方法同上.

4:循环中循环计数 i 的值

循环的过程中 i 的值一直在变。

// 以下循环除了执行了5次console.log(100)之外,还执行了5次 i++,意即i = i+1
for(let i=0;i<5;i++){
    console.log(100);
}
// 以上循环可以改写成
for(let i=0;i<5;){
    console.log(100);
    i = i + 1;
}
// 这样写,i = i+1就成了循环体的一部分。意即i的值每次循环都会改变。
// 这个循环执行了5次,每次循环对应 i 的值,依次为0,1,2,3,4

利用每次 i 的值,可以实现批量处理数据。

// 利用每次循环中i的值作为数组的下标,遍历数组中的每一个元素。
let arr = [1,2,3,4,5];
for(let i=0;i<arr.length;i++){
	console.log(arr[i])
}

// 利用每次循环中i的值作为数组的下标,遍历aDiv中的每一个html标签。
// 以下例子是给aDiv内的每一个div都添加一个事件
let aDiv = document.getElementsByTagName('div');
for(let i=0;i<arr.length;i++){
	console.log(aDiv[i]);
    aDiv[i].onclick = function(){console.log(10000)}
}

注意:

js 代码是在html的解析阶段执行的,循环也是在html的解析阶段执行完成的。

因此,页面渲染结束,循环一定执行完毕了,循环执行完毕后,循环中 i 的值肯定是最后一次变化的值。

我们又知道,事件函数内的代码是在hmtl渲染结束之后执行的,因此事件函数内只能获取 i 的最后一次变化的值。

// 以下循环代码,循环内添加事件,事件内打印i的值
// 因为是在事件函数内打印i的值,此时循环必定已经结束,打印的 i 值一定是5.
for(var i=0;i<5;i++){
    aBtn.onclick = function(){console.log(i)}
}

// 以下循环给多个div添加事件,原意是点击div让对应的div背景变红色。
// 但是因为事件函数触发时,i 的值统一是最大的那个值,因此导致错误的设置了不存在的div,导致报错。
// 解决办法是把var i=0 改成 let i = 0;至于为什么let没错,需要学到作用域才懂。
let aDiv = document.getElementsByTagName('div');
for(var i=0;i<arr.length;i++){
    aDiv[i].onclick = function(){
        aDiv[i].style.background = 'red'
    }
}

5:嵌套循环

嵌套循环意即循环里面又有循环。嵌套循环由内循环和外循环组成。

内部循环的循环计数 j 不能和外部循环的循环计数 i 名字一致。

// 以下嵌套循环的意思是:
// 执行5次内部循环
// for(let j=0;j<5;j++){
//    console.log(100);
// }
// 内部循环循环5次,内部循环代码体是console.log(100);
// 因此内部循环的意思是:
// 执行5次console.log(100);
for(let i=0;i<=4;i++){
	for(let j=0;j<5;j++){
        console.log(100);
    }
}
// 分析得出,外部循环循环1次,内部循环循环5次。外部循环循环结束时,内部循环循环了25次。
// 或者理解为,内部循环总共循环25次,分5次执行。

何时用嵌套循环

// 例如遍历二维数组的所有元素
let arr = [[1,2,3],[4,5,6],[7,8,9]];

// 不用循环----------------------------------------------------------------
console.log(arr[0][0]);
console.log(arr[0][1]);
console.log(arr[0][2]);

console.log(arr[1][0]);
console.log(arr[1][1]);
console.log(arr[1][2]);

console.log(arr[2][0]);
console.log(arr[2][1]);
console.log(arr[2][2]);

// 不用嵌套循环---------------------------------------------------------------
for(let i=0;i<arr[0].length;i++){
    console.log(arr[0][i]);
}

for(let i=0;i<arr[1].length;i++){
    console.log(arr[1][i]);
}

for(let i=0;i<arr[2].length;i++){
    console.log(arr[2][i]);
}

// 用嵌套循环-------------------------------------------------------------------
for(let j=0;j<arr.length;j++){
   for(let i=0;i<arr[j].length;i++){
       console.log(arr[j][i]);
   }
}

6.

break => 终止整个循环。
continue => 跳过当前循环,继续后面的循环。

四 循环进阶

1.标志位

标志位 => 自定义的变量,用来做判断。初始值一般是布尔值。

// 写程序判断这个数组里面的元素是不是全都能整除3.能就弹出能,不能就弹不能.(弹一次);
const arr = [123,12,333,72];
let flag = true;
// 循环检测,如果有任意一个元素不能整除3,标准位变成false.
    for (let i = 0; i < arr.length; i++) {
      if (arr[i] % 3 !== 0) {
        flag = false;
        // 但凡有一个不能整除3,则后续所有的循环判断都没必要做了.
        break;
      }
    }

if (flag) {
      alert('能');
    } else {
      alert('不能');
    }

上一篇:[Angular TypeScript报错]Cannot assign to read only property ‘outwardcolor‘ of object ‘[object Object]‘


下一篇:算法刷题系列(四)蓝桥杯python算法训练3