1、对象
object,对象是需要去创建的,最近学习了构造函数,构造函数用来创造对象
function People(name,age,sex) {
this.name = name;
this.age = age;
this.sex = sex
}
const person = new People('张三',25,'男')
function 函数名(){
函数名字必须是大驼峰
小括号里面的内容叫入参,是需要创建的对象的属性,比如:姓名;年龄;性别
大括号里面的数据叫做函数体,
然后用this关键字去关联对象的属性:
this.姓名 = 姓名;
this.年龄 = 年龄;
this.性别 = 性别;
}
然后用 const 对象名 = 关键字new 函数名(属性 例如:'姓名',’年龄‘,'性别'),这样就创建了一个对象object。
2、循环
现在学习的主要是for循环,for循环的循环体如下
for(let i = 0;i < 10; i++) {
}
先用for声明这是一个for循环,然后小括号里面的内容分别是(第一次循环的是从几开始;循环多少次;从开始依次向后循环0,1,2,3,4,5,6,7,8,9)大括号里面的内容是循环体,就是你循环后需要做的事情。
3、函数
函数的声明和写法
function fun(a,b) {
return a + b
}
函数由function去声明一个函数,就是告诉代码,这是一个函数,然后加上函数名,就是给函数起一个函数的名字(函数名一定要明确这个函数是做什么用的),然后加一个小括号,小括号里面可以有参数,可以没有内容,然后小括号后面跟一个大括号,大括号里面的内容就是你想让这个函数做的事情,叫做函数体
function 函数名(入参) {函数体}
4、family题目
接下来是许老师给我出的一道题,结合了对象,循环和函数,将三种方法结合使用,难度之大,写这篇文章的目的就是为了一步一步去理解这套题的整个解题思路,希望从中理解到这道题的难点,并将他解决
题目:有十四个对象(模拟数据),然后他们有三代人,然后将他们分别展现在页面上,一代在第一排,二代在第二排,三代在第三排,然后他们有夫妻,有子女,子女也可能有子女,展现在页面上的数据,一家人必须是同一背景颜色。
a、获取14个对象,每个对象中有8个属性,分别是:id,mateId,fn,Ln,sex,age,famly,like
id:每个人的固定编号
mateId:伴侣的id编号
fn:姓氏
Ln:名字
sex:性别
age:年龄
family:这个人是第几代人,由阿拉伯数字1.2.3代替
like:爱好
const data = {
code: 200,
msg: "success",
data: [
{
id: 1,
mateId: 2,
fn: "王",
Ln: "三",
sex: 1,
age: 58,
family: 1,
like: ["唱歌", "跳舞", "有钱"],
},
{
id: 13,
mateId: -1,
fn: "疾风剑豪",
Ln: "亚索",
sex: 1,
age: 40,
family: 3,
like: ["疾风亦有归途", "哈萨kei", "吹箫"],
},
{
id: 10,
mateId: 14,
fn: "王",
Ln: "根基",
sex: 1,
age: 18,
family: 3,
like: ["打架", "泡妞"],
},
{
id: 2,
mateId: 1,
fn: "李",
Ln: "四",
sex: 0,
age: 28,
family: 1,
like: ["唱歌", "跳舞", "玩游戏"],
},
{
id: 5,
mateId: 11,
fn: "孙",
Ln: "子多",
sex: 1,
age: 58,
family: 1,
like: ["萝莉"],
},
{
id: 4,
mateId: 3,
fn: "钱",
Ln: "多多",
sex: 0,
age: 28,
family: 1,
like: ["赚钱"],
},
{
id: 8,
mateId: 6,
fn: "郑",
Ln: "失败",
sex: 0,
age: 29,
family: 2,
like: ["看剧", "唱歌"],
},
{
id: 6,
mateId: 8,
fn: "王",
Ln: "围",
sex: 1,
age: 31,
family: 2,
like: ["打架", "热血高校"],
},
{
id: 14,
mateId: 10,
fn: "欧派",
Ln: "小小",
sex: 0,
age: 13,
family: 3,
like: ["吃木瓜"],
},
{
id: 3,
mateId: 4,
fn: "赵",
Ln: "四",
sex: 1,
age: 30,
family: 1,
like: ["开车", "钓鱼"],
},
{
id: 7,
mateId: 9,
fn: "赵",
Ln: "唯",
sex: 1,
age: 30,
family: 2,
like: ["看剧", "唱歌"],
},
{
id: 9,
mateId: 7,
fn: "郑",
Ln: "成功",
sex: 0,
age: 32,
family: 2,
like: ["游泳", "唱歌"],
},
{
id: 12,
mateId: -1,
fn: "赵",
Ln: "德龙东强",
sex: 1,
age: 6,
family: 3,
like: ["奥特曼", "泡妞"],
},
{
id: 11,
mateId: 5,
fn: "欧派",
Ln: "大大",
sex: 0,
age: 16,
family: 3,
like: ["钓凯子", "喝酒"],
},
],
};
b、在html中创建三个div,为了将1代2代3代的人分别放入不同的div中,并且分行
<!DOCTYPE html>
<html>
<head>
<title>家庭“对象”学习</title>
</head>
<body>
<div id="people1"></div>
<div id="people2"></div>
<div id="people3"></div>
</body>
</html>
c、创建css,先将页面的基本布局完善。
#people1 {
display: flex;
justify-content: center;
align-items: center;
}
#people2 {
display: flex;
justify-content: center;
align-items: center;
}
#people3 {
display: flex;
justify-content: center;
align-items: center;
}
d、开始整理解题思路
(1) 先创建一个空数组,用来放获取的十四个对象,为了后面用起来方便:
let peopleArray = [] // 所有的data里面的人物对象
(2) 用for循环循环14个对象,并将14个对象添加到空数组peopleArray中:
for (let i = 0; i < data.data.length; i++) {
peopleArray.push(data.data[i])
}
(3) 这个时候14个对象就已经放入了新数组peopleArray中,然后将数组中的十四个对象分代,将他们的1代2代3代分别循环放入不同的数组中,数组属性中的family属性就是这个人是第几代人:
let array1 = [] // 存储一代里面的所有人物对象
let array2 = [] // 存储二代里面的所有人物对象
let array3 = [] // 存储三代里面的所有人物对象
peopleArray.map((item) => {
if (item.family === 1) {
array1.push(item)
} else if (item.family === 2) {
array2.push(item)
} else {
array3.push(item)
}
})
这里用到了map循环,map循环和for循环的作用一致,只是写法不同,如果用for循环的话,写法就是这样的:
for(let i = 0;i < peopleArray.length;i++) {
if(peopleArray[i].family === 1) {
people1.push(peopleArray[i])
} else if (peopleArray[i].family === 2) {
people2.push(peopleArray[i])
} else {
people3.push(peopleArray[i])
}
}
(4) 创建一个函数,将peopleArray里面的对象数据平铺展现到数组里面,并将peopleArray里面的值改变顺序,1代2代3代的人按照1.2.3的顺序重新储存到数组里面
// 创建一个数组,为了将peopleArray里面的值放在里面
function sortList() {
// const list = [...array1, ...array2, ...array3] 这是es6的写法
const list = []
for (let i = 0; i < array1.length; i++) {
list.push(array1[i])
}
for (let i = 0; i < array2.length; i++) {
list.push(array2[i])
}
for (let i = 0; i < array3.length; i++) {
list.push(array3[i])
}
console.log(peopleArray); // 开始peopleArray的值是乱的
peopleArray = list
console.log(peopleArray); // 现在peopleArray的值是按照代数顺序排列的
}
(5) 将函数sortList()调用在全局中,为了在页面的最开始就直接进行排序(按照1代2代3代进行排序):
因为原数据是打乱的,所以如果不在开始进行排序,就会在后续操作的时候出现问题
在最后跑代码的时候,会先读取前面的人物,给他赋值familyId,导致后面他的家人会赋予不同的familyId,导致代码顺序错误。
源代码如下:
let peopleArray = [] // 所有的data里面的人物对象
let array1 = [] // 存储一代里面的所有人物对象
let array2 = [] // 存储二代里面的所有人物对象
let array3 = [] // 存储三代里面的所有人物对象
let familyList = [] // 存储家庭
// 将后端数据存到peopleArray中
for (let i = 0; i < data.data.length; i++) {
peopleArray.push(data.data[i])
}
// 分代
peopleArray.map((item) => {
if (item.family === 1) {
array1.push(item)
} else if (item.family === 2) {
array2.push(item)
} else {
array3.push(item)
}
})
sortList() // 将排序函数写在最上面,为了全局调用
function sortList() { // 创建一个数组,为了将peopleArray里面的值放在里面
// const list = [...array1, ...array2, ...array3]
const list = []
for (let i = 0; i < array1.length; i++) {
list.push(array1[i])
}
for (let i = 0; i < array2.length; i++) {
list.push(array2[i])
}
for (let i = 0; i < array3.length; i++) {
list.push(array3[i])
}
console.log(peopleArray);
peopleArray = list
console.log(list);
}
(6) 创建一个函数,为他的家庭进行标记(寻找他的家庭),并为他的家庭添加一个假数据(familyId)(假数据为了区分每一个家庭中的成员)(先创建好,这个函数,然后后面再进行操作)
// 创建一个函数,为每个人去标记他的家庭,寻找他的家人
function categorizeFamily() {
for (let i = 0 ; i < peopleArray.length; i++) {
const item = peopleArray[i] // 这一步循环并创建一个item是为了平铺整个peopleArray
里面的所有数据
console.log(item)
}
}
(7)创建一个函数,寻找伴侣,并为伴侣添加假数据(为了区分家庭的假数据,familyId)
// 寻找伴侣,并为伴侣添加familyId
function findMate(id,mateFamilyId) {
// 为函数添加两个参数,两个参数是为了对应伴侣的id和familyId,
// 确定是不是一家人,如果是一家人,就给他们相同的假数据familyId
for (let i = 0; i < peopleArray.length; i++) {
// 循环数组peopleArray,寻找此次循环的人的id,并找到metaId和他id相同的人
if(id === peopleArray[i].mateId) {
// 如果当前循环的的人的id和其他人的mateId有相等的,说明他们两个是一家人
peopleArray[i].familyId = mateFamilyId
// 如果确定他们两个人是一家人,那么就给这些人同样的一个假数据,就是familyId
}
}
}
(8)创建一个函数,这个函数的目的是为了寻找下一代子女,并为子女添加和上一代父母同样的familyId这个假数据
// 这个函数的目的是为了寻找子女,并且给子女传入新的数据
function findChildren(id,family,fn,fatherFamilyId){
// 这个函数传入四个参数,分别是id(为了知道子女的id是多少,方便找到这个人)
// family,知道子女的代数,因为只有三代,如果为第三代就可以不为他寻找子女
// fn,他的姓氏,如果上一代人有一样的姓氏,那么就可以知道他是谁的子女
// fatherFamilyId,知道了父亲的假数据familyId,并将父亲的这个数据赋值给子女
// 设置一个判断,如果他是第三代的人,那么就可以直接停止寻找,因为第三代没有子女
if(family === 3) return // return,直接停止函数,关键字
for(let i = 0; i < peopleArray.length; i++) {
// 循环数组,判断当前循环的人物是不是上一代父辈的代数 + 1,即是父辈的下一代
// 为什么是父辈的代数 + 1,因为循环,当循环第一个人的时候,是1代,1代不属于子女,
// 进入下一个人,一直到找到family为2的人,拿2和上一个人比较,2 = 1+1,则进入判断
if(peopleArray[i].family === family + 1){
// 然后继续判断当前的人物的姓氏和上一代人的那一个人是同姓,如果是同姓,
// 那么上一代同姓的人就是他的父辈,他们就是一家人
if(peopleArray[i].fn === fn) {
// 如果符合上面的两个判断,那么这两个就是一家人,就可以给子女赋值,给与一个
// 相同的假数据familyId
peopleArray[i].familyId === fatherFamilyId
}
}
}
}
(9)这个时候基本数据写完了,就可以去分类家庭函数里面调用函数并将他们的家庭、子女、夫妻进行配对,并赋值
let familyList = [] // 这个空数组为了储存family的值
// 分配家庭的函数,刚开始的时候已经写好的,现在开始往函数里面添加函数体
function categorizeFamily(){
for(let i = 0; i < peopleArray.length; i++) { //循环数组
const item = peopleArray[i]
// 建立一个item,并为他赋值,赋值为peopleArray里面的所有对象
// 因为赋的值是peopleArray[i],
所以item里面的值是平铺的所有peopleArray数组里面的对象
// 因为item是一次赋值永久使用的,所以这个地方用的const,而不是let或者var
// 这个地方平铺peopleArray数组,是为了接下来使用的时候更加方便,如果不平铺,也不会报错
// 开始进行函数体的书写
if(i === 0) {
// 这句话的意思是数组中的第一个对象,i是数组下标,他为0的时候指向的是数组中的第一个
对象
item.familyId = 1
// 这个时候为第一个对象添加一个假数据,familyId = 1
findMate(item.id,1)
// 这个时候调用寻找伴侣的函数,伴侣函数中的两个参数是(id,mateFamilyId)
// 因为之前在伴侣函数中写过如果id === mateId的时候,
他的familyId就等于mateFamilyId
// 所以,这个时候就开始循环寻找mateId和第一个人的id相同的人,并为他赋值family为1
findChildren(item.id,item.family,item.fn,1)
// 这个时候调用寻找子女的函数,子女中有四个参数(id,family,fn,fatherFamilyId)
/*
在子女的循环判断中写过,如果family === 3,就会直接停止整个函数,所以函数里面的
一定是family为2的人
参数就等于item.family,去判断是不是第三代
id === item.id是因为要用id去判断这个人到底是谁
fn === item.fn是为了知道这个子女的姓氏和上一代的人的姓氏是否相同,
或者他到底有没有上一代
fatherFamilyId === 1,是因为用第一个人去和下面的人循环比较,如果他们有和这个
人姓氏一样的人,那么就可以确定这个人是他的子女,因为我们上面排了序,所以第一个人
一定是一代也就是父辈,如果下面有和他姓氏一样的人,那么就为他的子女赋值,
familyId === 1
*/
familyList.push(1)
//在外层建立一个新的空数组,为了存储假数据family的值
} else { // 否则
if(item.familyId === undefind) {
// 这个判断的意思是,如果他没有familyId,则进入判断
if(item.sex === 0) continue
// 这个判断的意思是如果这个人是个女人,那么直接跳过这个人,进行下一个人
item.familyId = familyList.length + 1
// 如果这个人的familyId为空的时候,那么为他添加familyId,familyId的值
为familyList.length + 1是因为有一个家庭有了familyId的时候就会为
familyList的数组里面加1,他的长度就是1,第二个家庭就是2,那么就是1+1
findMate(item.id,familyList.length + 1)
// 寻找他的伴侣,并为他的子女赋值同样的familyId = familyList.length + 1
findChildren(item.id,item.family,item.fn,familyList + 1)
// 寻找他的子女,并为他的子女赋值同样的familyId = familyList.length + 1
familyList.push(familyList.length + 1)
// 每当有一个家庭添加了familyId,就将这个值添加到familyList数组里面
} else {
// 如果循环的这个人已经被添加了familyId的话就为他的子女和伴侣添加familyId
findMate(item.id,item.familyId)
findChildren(item.id,item.family,item.fn,item.familyId)
}
}
}
}
(10) 将写好的数据渲染到页面上,先写好不同颜色的四个css,并给与他们不同的名称
.family1{
background-color = red
}
.family2{
background-color = green
}
.family3{
background-color = blue
}
.family4{
background-color = gold
}
(11)将上面的一代二代三代的所有名字渲染在页面上
// 一代人物,储存数组是array1
for (let i = 0;i < array1.length;i++) {
// 在写的时候必须要用+=,因为如果写等于他会循环到最后一个后写在页面上,会覆盖前面的循环
document.getElementById("people1").innerHtml +=
array1[i].fn + array1[i].ln
}
// 二代人物,储存数组是array2
for (let i = 0;i < array2.length;i++) {
document.getElementById("people2").innerHtml +=
array2[i].fn + array2[i].ln
}
// 三代人物,储存数组是array3
for (let i = 0;i < array3.length;i++) {
document.getElementById("people3").innerHtml +=
array3[i].fn + array3[i].ln
}
这个时候展现在页面上的内容是:
(11)这个时候把所有人物的名字打印在了页面上,但是我们需要让一个家庭的人显示同一个背景颜色,那么我们继续渲染页面,进行二次渲染
// 一代渲染
for (let i = 0; i < array1.length; i++) {
document.getElementById('people1').innerHTML +=
"<div class='style family" + array1[i].familyId + "'>" +
array1[i].fn + array1[i].Ln + "</div>"
}
// 二代渲染
for (let i = 0; i < array2.length; i++) {
document.getElementById('people2').innerHTML +=
"<div class='style family" + array2[i].familyId + "'>" +
array2[i].fn + array2[i].Ln + "</div>"
}
// 三代渲染
for (let i = 0; i < array3.length; i++) {
document.getElementById('people3').innerHTML +=
"<div class='style family" + array3[i].familyId + "'>" +
array3[i].fn + array3[i].Ln + "</div>"
}
渲染后的样式: