一、对象
1、对象概念
- 对象(object):JavaScript里的一种数据类型
- 可以理解为是一种无序的数据集合
- 用来描述某个事物,例如描述一个人
人有姓名、年龄、性别等信息、还有吃饭睡觉打代码等功能
如果用多个变量保存则比较散,用对象比较统一 - 比如描述 班主任 信息:
静态特征 (姓名, 年龄, 身高, 性别, 爱好) => 可以使用数字, 字符串, 数组, 布尔类型等表示
动态行为 (点名, 唱, 跳, rap) => 使用函数表示
2、对象使用
(1)对象声明语法
(2) 对象有属性和方法组成
属性:信息或叫特征(名词)。 比如 手机尺寸、颜色、重量等…(变量)
方法:功能或叫行为(动词)。 比如 手机打电话、发短信、玩游戏…(函数)
- 属性
数据描述性的信息称为属性
属性都是成对出现的,包括属性名和值,它们之间使用英文 : 分隔
多个属性之间使用英文 , 分隔
属性就是依附在对象上的变量(外面是变量,对象内是属性)
属性名可以使用 “” 或 ‘’,一般情况下省略,除非名称遇到特殊符号如空格、中横线等
-
属性访问
声明对象,并添加了若干属性后,可以使用 . 或 [] 获得对象中属性对应的值,称之为属性访问。
-
方法
数据行为性的信息称为方法,如跑步、唱歌等,一般是动词性的,其本质是函数。
方法是由方法名和函数两部分构成,它们之间使用 : 分隔
多个属性之间使用英文 , 分隔
方法是依附在对象中的函数
方法名可以使用 “” 或 ‘’,一般情况下省略,除非名称遇到特殊符号如空格、中横线等
- 方法调用
声明对象,并添加了若干方法后,可以使用 . 调用对象中函数,称之为方法调用
对象方法调用可以传递参数
3、操作对象
(1)增删改查
- 增加属性,可以动态为对象添加属性
- 增加方法,动态为对象添加方法
添加属性/方法就是:对象如果有这个属性/方法相当于重新赋值/定义;对象如果没有这个属性/方法相当于动态添加一个属性/方法
4、遍历对象
注意,k就是一个循环变量,第一次循环等于’uname‘,第二次等于’age‘……
这里,使用 for in 遍历,通过 k 获得对象的属性名, 对象名[k] 获得 属性值
不能用对象名.[k]或者对象名.[‘k’] 遍历获得属性值,因为k是变量不是属性名,属性中只有uname等,没有一个叫k的。要与查询对象区分开。
5、内置对象
(1)内置对象概念
JavaScript内部提供的对象,包含各种属性和方法给开发者调用,如document.write()、console.log()
(2) 内置对象Math
- Math对象是JavaScript提供的一个“数学高手”对象
- 提供了一系列做数学运算的方法
- 方法有:
random:生成0-1之间的随机数(包含0不包括1)
ceil:向上取整
floor:向下取整
max:找最大数
min:找最小数
pow:幂运算
abs:绝对值 - 可以在 mdn 中查找具体方法的介绍
(3)生成任意范围随机数
- 如何生成0-10的随机数呢?
Math.floor(Math.random() * (10 + 1))
- 如何生成5-10的随机数?
Math.floor(Math.random() * (5 + 1)) + 5
- 如何生成N-M之间的随机数(包括N、M)
Math.floor(Math.random() * (M - N + 1)) + N
一般封装在函数中,可以直接调用:
<script>function getRandom(x,y){return Math.floor(Math.random()*(y-x+1))+x}let r = getRandom(1,10) //随机返回1-10的整数console.log(r)</script>
二、案例–学生信息表(对象)
请把下面数据中的对象打印出来:
// 定义一个存储了若干学生信息的数组
let students = [
{name: ‘小明’, age: 18, gender: ‘男’, hometown: ‘河北省’},
{name: ‘小红’, age: 19, gender: ‘女’, hometown: ‘河南省’},
{name: ‘小刚’, age: 17, gender: ‘男’, hometown: ‘山西省’},
{name: ‘小丽’, age: 18, gender: ‘女’, hometown: ‘山东省’}
]
① 首先,不管具体的数据内容,先把表格样子整出来(html+css)
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>table{width: 600px;text-align: center;border-collapse: collapse; //合并表格框 }caption{font-weight: 600;font-size: 18px;margin-bottom: 20px;}th,td{height: 40px;border:1px solid #ccc;cursor: pointer;}tr:first-child{background-color: #ddd;}tr:not(first-child):hover{ //只有第一行鼠标悬停不会变灰色background-color: #eee;}</style>
</head>
<body><table><caption>学生信息表</caption> //内容先随便写点固定的占位<tr><th>序号</th> <th>姓名</th><th>年龄</th><th>性别</th> <th>家乡</th> </tr><tr><td>1</td><td>小明</td><td>18</td><td>男</td><td>河北省</td></tr><tr><td>1</td><td>小明</td><td>18</td><td>男</td><td>河北省</td></tr><tr><td>1</td><td>小明</td><td>18</td><td>男</td><td>河北省</td></tr><tr><td>1</td><td>小明</td><td>18</td><td>男</td><td>河北省</td></tr><tr><td>1</td><td>小明</td><td>18</td><td>男</td><td>河北省</td></tr></table>
</body>
</html>
做完如下,样子有了,不过里面的数据是没有意义的。
② 利用JS把数据传进去,能动态改变
因为要遍历数组,肯定需要用到循环,循环不能放在document.write( )中,所以输出分为三块,首先打印头部和尾部两块,也就是循环前面和后面的内容。
其次通过循环打印表格每一位同学信息,先循环,在循环里面打印。
document.write()中的内容结构和原来用来的静态数据结构类似,比如都是
<table>
里面放<caption>
,然后<tr>
等,所以要先用静态数据将格式做出来,再填入动态数据。
完整代码:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>table{width: 600px;text-align: center;border-collapse: collapse; //合并表格框 }caption{font-weight: 600;font-size: 18px;margin-bottom: 20px;}th,td{height: 40px;border:1px solid #ccc;cursor: pointer;}tr:first-child{background-color: #ddd;}tr:not(first-child):hover{ //除了第一行鼠标悬停都变灰色background-color: #eee;} </style>
</head>
<body><script>let students = [{name: '小明', age: 18, gender: '男', hometown: '河北省'},{name: '小红', age: 19, gender: '女', hometown: '河南省'},{name: '小刚', age: 17, gender: '男', hometown: '山西省'},{name: '小丽', age: 18, gender: '女', hometown: '山东省'},{name: '小胡', age: 19, gender: '女', hometown: '河南省'},]// 第一步 打印表格的头部和尾部document.write(`<table><caption>学生信息表</caption><tr><th>序号</th><th>姓名</th><th>年龄</th><th>性别</th><th>家乡</th></tr>`)// 中间遍历行数 for (let i = 0 ;i < students.length; i++) {document.write(`<tr><td>${i+1}</td><td>${students[i].name}</td><td>${students[i].age}</td><td>${students[i].gender}</td><td>${students[i].hometown}</td></tr>`)}// 尾部 document.write(`</table>`) </script>
</body>
</html>
三、案例–猜数字游戏(随机数)
需求:程序随机生成 1~10 之间的一个数字,用户输入一个数字
①:如果大于该数字,就提示,数字猜大了,继续猜
②:如果小于该数字,就提示,数字猜小了,继续猜
③:如果猜对了,就提示猜对了,程序结束
<script>function getRandom(x,y){return Math.floor(Math.random()*(y-x+1))+x}let r = getRandom(1,10) while(true){let n = prompt('请输入猜的数')if(n>r){alert('猜大了')}else if (n<r){alert('猜小了')}else {alert('对了')break // 退出循环}}</script>
四、综合案例–学成在线
(总体采用的策略还是先写好html和css,然后在利用JS添加数据渲染)
在前面的综合案例,如柱状图里面,有循环动态加入数据的,但是因为for循环不能写在
document.write()
中,所以采用的是先写盒子的上一半<div>
,再写下一半</div>
,这样就能将for循环夹在中间(浏览器显示的时候就会在盒子里面)且没写入document.write()
。
但是这个案例盒子太多,结构比较复杂,如下
这样拆盒子写法太繁琐了,有第二种方法,将<script>
写在需要渲染的盒子标签里面。
在这里头部(精品推荐+查看全部)都不用传入数据动态改变,需要渲染的只有下面具体的课程,也就是 ul
中的 li
。于是就在 ul
标签里面放入 script
,利用JS语言循环传入数据。(data为存储数据的数组)。
完整代码:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><link rel="stylesheet" href="./index.css">
</head>
<body> <div class="box"><div class="head"><h3>精品推荐</h3><p>查看全部</p></div> <div class="body"><ul><script>let data = [{src: 'images/course01.png',title: 'Think PHP 5.0 博客系统实战项目演练',num: 1125},{src: 'images/course02.png',title: 'Android 网络动态图片加载实战',num: 357},{src: 'images/course03.png',title: 'Angular2 大前端商城实战项目演练',num: 22250},{src: 'images/course04.png',title: 'Android APP 实战项目演练',num: 389},{src: 'images/course05.png',title: 'UGUI 源码深度分析案例',num: 124},{src: 'images/course06.png',title: 'Kami2首页界面切换效果实战演练',num: 432},{src: 'images/course07.png',title: 'UNITY 从入门到精通实战案例',num: 888},{src: 'images/course08.png',title: 'Cocos 深度学习你不会错过的实战',num: 590} ] for (let i =0; i<data.length ; i++){document.write(`<li><img src="${data[i].src}" alt=""></img><h4>${data[i].title}</h4><div class="info"><span>高级</span> • <span>${data[i].num}</span>人在学习</div></li> `)} </script></ul></div></div>
</body>
</html>
*{margin: 0;padding: 0;
}
ul{list-style: none;
}
img{width: 100%;
}
body{background-color: #f3f5f7;
}
.box{width: 1200px;margin: 30px auto;
}
.box .head{display: flex;justify-content: space-between;margin-bottom: 15px;
}
.box .head h3{font-size: 20px;color: #494949;
}
.box .head p{margin-right: 30px;margin-top: 10px;font-size: 12px;color: #a5a5a5;
}
.box .body ul{display: flex;flex-wrap: wrap;
}.box .body ul li{width: 228px;height: 270px;background-color: #FFF;margin-right: 15px;margin-bottom: 15px;transition: all 0.3s;
}.box .body ul li:nth-child(6n){margin-right: 0;
}
.box .body ul li:hover{margin-top:-8px;box-shadow: 2px 2px 2px 2px rgba(0,0,0,.3);
}.box .body ul li h4{margin: 20px 20px 20px 25px;font-size: 14px;color: #050505;font-weight: 400;
}
.box .body ul li .info{margin-left: 25px;font-size: 12px;color: #999;
}
.box .body ul li .info span{color: #ff7c2d;
}
五、方法总结:
通过案例学生信息表总结方法,数据渲染前的代码:
<table><caption>学生信息表</caption><tr><th>序号</th><th>姓名</th><th>年龄</th><th>性别</th><th>家乡</th></tr><tr><td>1</td><td>小马</td><td>12</td><td>男</td><td>河南</td></tr><tr><td>2</td><td>小马</td><td>12</td><td>男</td><td>河南</td></tr>
</table>
写好html+css后,用数据渲染,可以有两种方法,第一种就是之前用的,所有代码都写在
script
中,把盒子标签<div></div>
拆开用document.write
写出来,就能在中间通过循环使用数据渲染,这种方法比较麻烦,适合盒子嵌套少的结构简单的,如下:
第二种是找到需要数据渲染的盒子标签,在里面放入script
标签,而对于其他的不需要数据渲染的盒子,就不用管。这种方法适合结构复杂盒子嵌套很多的。如下:(左边是原来静态的没渲染数据的代码,从中可以发现,需要渲染的是从第二个<tr>
开始的全部<tr>
,于是在这里放入script
。)
六、拓展、术语认识
1、数据类型
- 分为简单数据类型和复杂数据类型
- 简单类型又叫做基本数据类型或者值类型,复杂类型又叫做引用类型。
值类型:简单数据类型/基本数据类型,在存储时变量中存储的是值本身,因此叫做值类型,如string ,number,boolean,undefined,null
引用类型:复杂数据类型,在存储时变量中存储的仅仅是地址(引用),因此叫做引用数据类型,如通过 new 关键字创建的对象(系统对象、自定义对象), Object、Array、Date等
2、数据类型的存储方式
-
简单数据类型存放到栈里面
栈(操作系统):由操作系统自动分配释放存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈;
-
引用数据类型存放到堆里面
堆(操作系统):存储复杂类型(对象),一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。
3、例子
第一个结果为10,第二个结果为20
原因:
第一个是简单数据类型,就存放在栈中,num1=10,就是num1指向栈中存的10,同理num2,改变num2的值,只改变了num2在栈中存放的10,所以num1值不变;
第二个是复杂数据类型,obj1指向栈中一块地址,然后该地址指向堆中一块区域,存放的obj1的值。obj2 = obj1,即在栈中,obj2和obj1一样,因为复杂数据类型栈中存放的是地址,所以obj2和obj1指向了一个地址,然后该地址指向堆中一个数据,改变obj2的值,该数据就变了,obj1指向的也是该数据,所以也变了。