文章目录
- JavaScript
- 用户订单信息案例
- 面试题
- ATM取款机案例
- 九九乘法表
- 冒泡排序
- 综合案例——根据数据生成柱形图
- 时间小案例
- 学生信息表案例
- 随机数小案例
- 随机点名小案例
- 猜数字案例
- 学成在线小案例
- 专业术语
- 基本数据类型和引用数据类型
- 面向过程编程 POP(Process-oriented programming)
- 面向对象编程 OOP (Object Oriented Programming)
- 对象
- 类 class
- 面向对象版tab栏案例
- 构造函数和原型
- 继承
- ES5 中的新增方法
- 查询商品案例
- 函数的定义和调用
- this
- 严格模式
- 高阶函数
- 闭包
- 闭包的案例
- 思考题
- 递归
- 浅拷贝和深拷贝
- 正则表达式
- 正则表达式的组成
- 用户名验证小案例
- 验证座机号码小案例
- 表单验证小案例
- 正则表达式中的替换
- 过滤敏感词汇小案例
- ES6
- ES6 的新增语法
- 经典面试题
- 面试题
- ES6 的内置对象扩展
- 网盘资源(仅供学习使用,不可商用!!!)
JavaScript
初学者体验
html
<!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="./js.css">
</head>
<body>
<button class="pink">按钮</button>
<button>按钮</button>
<button>按钮</button>
<script>
let btns = document.querySelectorAll('button')
for( let i = 0; i < btns.length; i++){
btns[i].addEventListener('mouseover', function(){
document.querySelector('.pink').className = ''
this.className = 'pink'
})
}
</script>
</body>
</html>
css
.pink {
background-color: pink;
}
JavaScript 书写位置
1. 内部 JavaScript
<!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="./js.css">
</head>
<body>
<h1>123</h1>
<script>
alert('你好, js')
</script>
</body>
</html>
2. 外部 JavaScript
html
<!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="./js.css">
</head>
<body>
<h1>123</h1>
<script src="./my.js"></script>
</body>
</html>
js
alert('Rihood')
3. 内联 JavaScript
JavaScript 注释
了解JavaScript结束符
JavaScript 输入输出语法
字面量
变量
变量案例:交换变量的值
变量命名规则与规范
变量拓展——let和var的区别
变量拓展——数组
数据类型
数字类型(number)
字符串类型(string)
模板字符串
布尔类型(boolean)
未定义类型(undefined)
null(空类型)
控制台输出语句和检测数据类型(typeof)
let age = 21
let uname = 'Rihood'
let flag = true
let pwd
console.log(typeof age)
console.log(typeof uname)
console.log(typeof flag);
console.log(typeof pwd);
数据类型转换
隐式转换
显式转换
用户订单信息案例
html
<!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="./js.css">
</head>
<body>
<script src="./my.js"></script>
</body>
</html>
css
* {
margin: 0;
padding: 0;
}
table {
margin: 0 auto;
text-align: center;
/* border-collapse 用于表格属性, 表示表格的两边框合并为一条。 */
border-collapse: collapse;
}
table th, td {
border: 1px solid #000;
padding: 15px;
}
table caption {
margin: 15px 0;
}
JavaScript
let price = +prompt('please input price:')
let num = +prompt('please input the number:')
let address = prompt('please input address:')
let total = price * num
document.write(`
<table>
<caption>
<h2>订单确认</h2>
</caption>
<tr>
<th>商品名称</th>
<th>商品价格</th>
<th>商品数量</th>
<th>总价</th>
<th>收货地址</th>
</tr>
<tr>
<td>华为青春Pro</td>
<td>${price}</td>
<td>${num}</td>
<td>${total}</td>
<td>${address}</td>
</tr>
</table>
`)
算术运算符
赋值运算符
一元运算符
面试题
答案:7
比较运算符
逻辑运算符
运算符优先级
表达式和语句
分支语句
if语句
三元运算符
switch语句
循环结构
while 循环
for 循环
for…in循环
for in 与 for of 它们之间的主要区别在于它们的迭代方式
循环退出(continue、break)
ATM取款机案例
<!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>
</head>
<body>
<script>
// 1. 不断的弹出对话框
// 3. 金额的变量
let money = 100
while (true) {
let str = prompt(`请您选择操作:
1. 存钱
2. 取钱
3. 查看余额
4. 退出
`)
// 2. 除非输入的是4 则退出循环 break
if (str === '4') {
break
}
// 4. switch 加减操作
switch (str) {
case '1':
let cun = +prompt('请您输入存钱的金额:')
// money = money + cun
money += cun
break
case '2':
let qu = +prompt('请您输入取钱的金额:')
money -= qu
break
case '3':
alert(`您卡上的余额是${money}元`)
break
}
}
</script>
</body>
</html>
断点调试
九九乘法表
html
<!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>
div {
display: inline-block;
height: 25px;
line-height: 25px;
margin: 5px;
background-color: pink;
padding: 0 10px;
border: 1px solid hotpink;
color: deeppink;
border-radius: 5px;
box-shadow: 2px 2px 2px rgba(0, 0, 0, .2);
text-align: center;
}
</style>
</head>
<body>
<script>
// 外层打印几行
for (let i = 1; i <= 9; i++) {
// 里层打印几个星星
for (let j = 1; j <= i; j++) {
// 只需要吧 ★ 换成 1 x 1 = 1
document.write(`
<div> ${j} x ${i} = ${j * i} </div>
`)
}
document.write('<br>')
}
</script>
</body>
</html>
数组
操作数组
1. 数组增加新的数据(push、unshift)
2. 数组删除元素(pop、shift、splice)
冒泡排序
综合案例——根据数据生成柱形图
html
<!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="./trial.css">
</head>
<body>
<script src="./trial.js"></script>
</body>
</html>
js
let arr = []
for(let i = 1; i <= 4; i++){
let tmp = +prompt(`请输入第${i}季度的数据`)
arr.push(tmp)
}
// console.log(arr)
document.write(`<div class="box">`)
//循环4个柱子
for(let i = 0; i < arr.length; i++){
document.write(`
<div style="height: ${arr[i]}px;">
<span>${arr[i]}</span>
<h4>第${i + 1}季度</h4>
</div>
`)
}
document.write(`</div>`)
css
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.box {
display: flex;
width: 700px;
height: 300px;
border-left: 2px solid pink;
border-bottom: 2px solid pink;
margin: 50px auto;
/* 平分剩余空间 */
justify-content: space-around;
/* 贴着下面,即侧轴正方向 */
align-items: flex-end;
text-align: center;
}
.box>div {
display: flex;
width: 60px;
background-color: orangered;
flex-direction: column;
justify-content: space-between;
}
.box div span {
margin-top: -30px;
}
.box div h4 {
margin-bottom: -33px;
width: 80px;
margin-left: -10px;
}
函数
函数传参
函数返回值
作用域
匿名函数
立即执行函数
多个立即执行函数必须用分号结尾!!!
时间小案例
html
<!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>
</head>
<body>
<script>
let second = +prompt('please input whole seconds:')
function getTimes(t) {
// parseInt() 函数可解析一个字符串,并返回一个整数。
let h = parseInt(t / 60 / 60 % 24)
let m = parseInt(t / 60 % 60)
let s = parseInt(t % 60)
h = h < 10 ? '0' + h : h
m = m < 10 ? '0' + m : m
s = s < 10 ? '0' + s : s
return `<br>计算之后的时间是${h}小时${m}分${s}秒`
}
let str = getTimes(second)
document.write(str)
</script>
</body>
</html>
细节
对象
对象外是函数,对象内是方法
对象的操作——增删改查
遍历对象
学生信息表案例
html
<!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="./func.css">
</head>
<body>
<h2>学生信息</h2>
<p>将数据渲染到页面中...</p>
<script>
let stu = [
{name: '小明', age: 18, gender: '男', hometown: '海南省'},
{name: '小红', age: 19, gender: '女', hometown: '湖南省'},
{name: '小刚', age: 17, gender: '男', hometown: '广东省'},
{name: '小丽', age: 18, gender: '女', hometown: '江西省'},
{name: '小丽', age: 18, gender: '女', hometown: '辽宁省'},
{name: '小丽', age: 18, gender: '女', hometown: '福建省'}
]
document.write(`
<table>
<caption>学生列表</caption>
<tr>
<th>序号</th>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
<th>家乡</th>
</tr>
`)
for (let i = 0; i < stu.length; i++) {
document.write(`
<tr>
<td>${i + 1}</td>
<td>${stu[i].name}</td>
<td>${stu[i].age}</td>
<td>${stu[i].gender}</td>
<td>${stu[i].hometown}</td>
</tr>
`)
}
document.write(`
</table>
`)
</script>
</body>
</html>
css
table {
width: 600px;
/* 文字水平居中 */
text-align: center;
}
table,
th,
td {
border: 1px solid #ccc;
/* 边框合并 */
border-collapse: collapse;
}
caption {
font-size: 18px;
margin-bottom: 10px;
font-weight: 700;
}
tr {
height: 40px;
cursor: pointer;
}
table tr:nth-child(1) {
background-color: #ddd;
}
/* 除了第一行之外 */
table tr:not(:first-child):hover {
background-color: #eee;
}
内置对象
可以参考一下Math对象在线文档
或者国外的官方文档:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Math/random
随机数小案例
html
<!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="./func.css">
</head>
<body>
<script>
let arr = ['赵云', '黄忠', '关羽', '张飞', '马超', '刘备', '曹操']
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min
}
let random = getRandom(0, arr.length - 1)
document.write(arr[random])
</script>
</body>
</html>
随机点名小案例
html
<!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="./func.css">
</head>
<body>
<script>
let arr = ['赵云', '黄忠', '关羽', '张飞', '马超', '刘备', '曹操']
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min
}
let random = getRandom(0, arr.length - 1)
document.write(`全部的人:` + arr)
document.write(`<br>`)
document.write(`点到的人:` + arr[random])
arr.splice(random, 1)
document.write(`<br>`)
document.write(`剩余的人:` + arr)
</script>
</body>
</html>
猜数字案例
html
<!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="./func.css">
</head>
<body>
<script>
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min
}
let random = getRandom(1, 10)
while (true) {
let num = +prompt(`please input a digit:`)
if (random < num) {
alert(`你猜大了`)
}
else if (random > num) {
alert(`你猜小了`)
}
else {
alert(`Bingo!`)
break
}
}
</script>
</body>
</html>
学成在线小案例
html
<!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>学成在线首页</title>
<link rel="stylesheet" href="./practice5.css">
</head>
<body>
<!-- 4. box核心内容区域开始 -->
<div class="box w">
<div class="box-hd">
<h3>精品推荐</h3>
<a href="#">查看全部</a>
</div>
<div class="box-bd">
<ul class="clearfix">
<script>
let data = [
{
src: './img/course01.png',
title: 'Think PHP 5.0 博客系统实战项目演练',
num: 1125
},
{
src: './img/course02.png',
title: 'Android 网络动态图片加载实战',
num: 357
},
{
src: './img/course03.png',
title: 'Angular2 大前端商城实战项目演练',
num: 22250
},
{
src: './img/course04.png',
title: 'Android APP 实战项目演练',
num: 389
},
{
src: './img/course05.png',
title: 'UGUI 源码深度分析案例',
num: 124
},
{
src: './img/course06.png',
title: 'Kami2首页界面切换效果实战演练',
num: 432
},
{
src: './img/course07.png',
title: 'UNITY 从入门到精通实战案例',
num: 888
},
{
src: './img/course08.png',
title: '我会变,你呢?',
num: 590
},
{
src: './img/course08.png',
title: '我会变,你呢?',
num: 590
}
]
// 根据数据的个数来渲染 到底有多少个小li
// console.log(data.length)
for (let i = 0; i < data.length; i++) {
document.write(`
<li>
<img src=${data[i].src} alt="">
<h4>
${data[i].title}
</h4>
<div class="info">
<span>高级</span> • <span> ${data[i].num}</span>人在学习
</div>
</li>
`)
}
</script>
</ul>
</div>
</div>
</body>
</html>
css
* {
/* 消除内外边距 */
margin: 0;
padding: 0;
}
.w {
width: 1200px;
/* 居中 */
margin: auto;
}
body {
background-color: #f3f5f7;
}
li {
list-style: none;
}
a {
text-decoration: none;
}
/* 清除浮动 */
.clearfix:before,
.clearfix:after {
content:"";
display:table;
}
.clearfix:after {
clear:both;
}
/* zoom: 1、zoom: 100% 和 zoom: normal 都是等价的,它表示将元素缩放至原来 1 倍的大小,这看上去和原来没有什么区别。不过在 IE8 及以下的浏览器里,由于 zoom 会触发 hasLayout,从而使元素获得清除浮动的特性。对于旧版本 IE 来说,这么清除浮动的副作用是比较小的,代码也是最短的,所以大家多半会选择这种方式来清除浮动。 */
.clearfix {
*zoom:1;
}
/* zoom表示放大的意思,后边跟着一个数值,写几就将元素放大几倍
* zoom:1表示不放大元素,但是通过该样式可以开启hasLayout
* zoom这个样式,只在IE中支持,其他浏览器都不支持 */
.box {
margin-top: 30px;
}
.box-hd {
height: 45px;
}
.box-hd h3 {
float: left;
font-size: 20px;
color: #494949;
}
.box-hd a {
float: right;
font-size: 12px;
color: #a5a5a5;
margin-top: 10px;
margin-right: 30px;
}
/* 把li 的父亲ul 修改的足够宽一行能装开5个盒子就不会换行了 */
.box-bd ul {
width: 1225px;
}
.box-bd ul li {
position: relative;
top: 0;
float: left;
width: 228px;
height: 270px;
background-color: #fff;
margin-right: 15px;
margin-bottom: 15px;
transition: all .3s;
cursor: pointer;
}
.box-bd ul li:hover {
top: -8px;
box-shadow: 2px 2px 2px 2px rgba(0,0,0,.3);
}
.box-bd ul li img {
width: 100%;
}
.box-bd ul li h4 {
margin: 20px 20px 20px 25px;
font-size: 14px;
color: #050505;
font-weight: 400;
}
.box-bd .info {
margin: 0 20px 0 25px;
font-size: 12px;
color: #999;
}
.box-bd .info span {
color: #ff7c2d;
}
专业术语
基本数据类型和引用数据类型
面向过程编程 POP(Process-oriented programming)
面向对象编程 OOP (Object Oriented Programming)
在面向对象程序开发思想中,每一个对象都是功能中心,具有明确分工。
面向对象编程具有灵活、代码可复用、容易维护和开发的优点,更适合多人合作的大型软件项目。
对象
类 class
创建类
类 constructor 构造函数
字面量、构造函数、new创建对象
类添加方法
继承
super 关键字
注意:
-
继承中,如果实例化子类输出一个方法,先看子类有没有这个方法,如果有就先执行子类的
-
继承中,如果子类里面没有,就去查找父类有没有这个方法,如果有,就执行父类的这个方法(就近原则)
-
如果子类想要继承父类的方法,同时在自己内部扩展自己的方法,利用super 调用父类的构造函数,super 必须在子类this之前调用
// 父类有加法方法
class Father {
constructor(x, y) {
this.x = x;
this.y = y;
}
sum() {
console.log(this.x + this.y);
}
}
// 子类继承父类加法方法 同时 扩展减法方法
class Son extends Father {
constructor(x, y) {
// 利用super 调用父类的构造函数 super 必须在子类this之前调用,放到this之后会报错
super(x, y);
this.x = x;
this.y = y;
}
subtract() {
console.log(this.x - this.y);
}
}
var son = new Son(5, 3);
son.subtract(); //2
son.sum();//8
三个注意点:
- constructor中的this指向的是new出来的实例对象
- 自定义的方法,一般也指向的new出来的实例对象
- 绑定事件之后this指向的就是触发事件的事件源
面向对象版tab栏案例
完整代码
html
<!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>面向对象 Tab</title>
<link rel="stylesheet" href="./styles/tab.css">
<link rel="stylesheet" href="./styles/style.css">
</head>
<body>
<main>
<h4>
Js 面向对象 动态添加标签页
</h4>
<div class="tabsbox" id="tab">
<!-- tab 标签 -->
<nav class="firstnav">
<ul>
<li class="liactive">
<span>测试1</span>
<span class="iconfont icon-guanbi"></span>
</li>
<li>
<span>测试2</span>
<span class="iconfont icon-guanbi"></span>
</li>
<li>
<span>测试3</span>
<span class="iconfont icon-guanbi"></span>
</li>
</ul>
<div class="tabadd">
<span>+</span>
</div>
</nav>
<!-- tab 内容 -->
<div class="tabscon">
<section class="conactive">测试1</section>
<section>测试2</section>
<section>测试3</section>
</div>
</div>
</main>
<script src="js/tab.js"></script>
</body>
</html>
css
* {
margin: 0;
padding: 0;
}
ul li {
list-style: none;
}
main {
width: 960px;
height: 500px;
border-radius: 10px;
margin: 50px auto;
}
main h4 {
height: 100px;
line-height: 100px;
text-align: center;
}
.tabsbox {
position: relative;
width: 900px;
margin: 0 auto;
height: 400px;
border: 1px solid lightsalmon;
}
nav ul {
/* 清除浮动 */
overflow: hidden;
}
nav ul li {
position: relative;
float: left;
width: 100px;
height: 50px;
line-height: 50px;
text-align: center;
border-right: 1px solid #ccc;
}
nav ul li.liactive {
border-bottom: 2px solid #fff;
z-index: 9;
}
#tab input {
width: 80%;
height: 60%;
}
nav ul li span:last-child {
position: absolute;
display: inline-block;
top: -18px;
right: 0;
user-select: none;
font-size: 12px;
height: 20px;
}
.tabadd {
position: absolute;
/* width: 100px; */
top: 0;
right: 0;
}
.tabadd span {
display: block;
float: right;
margin: 10px;
width: 20px;
height: 20px;
line-height: 20px;
text-align: center;
border: 1px solid #ccc;
/* 元素和子元素的文本将无法被选中 */
user-select: none;
}
.tabscon {
position: absolute;
width: 100%;
height: 300px;
padding: 30px;
top: 50px;
left: 0px;
box-sizing: border-box;
border-top: 1px solid #ccc;
}
.tabscon section,
.tabscon section.conactive {
display: none;
width: 100%;
height: 100%;
}
.tabscon section.conactive {
display: block;
}
js
var that;
var cnt = 0
class Tab {
constructor(id) {
that = this
this.main = document.querySelector(id)
this.add = this.main.querySelector('.tabadd')
this.ul = this.main.querySelector('.firstnav ul:first-child')
this.fsection = this.main.querySelector('.tabscon')
this.init()
}
init() {
this.updateNode()
// init初始化操作让相关元素绑定事件
this.add.onclick = this.addTab
for (var i = 0; i < this.lis.length; i++) {
this.lis[i].index = i
this.lis[i].onclick = this.toggleTab
this.remove[i].onclick = this.removeTab
this.spans[i].ondblclick = this.editTab
this.sections[i].ondblclick = this.editTab
cnt = i + 1
}
}
updateNode() {
this.lis = this.main.querySelectorAll('li')
this.sections = this.main.querySelectorAll('section')
this.remove = this.main.querySelectorAll('.icon-guanbi')
this.spans = this.main.querySelectorAll('.firstnav li span:first-child')
}
toggleTab() {
that.clearClass()
this.classList.add('liactive')
that.sections[this.index].classList.add('conactive')
}
clearClass() {
for (var i = 0; i < this.lis.length; i++) {
this.lis[i].classList.remove('liactive')
this.sections[i].classList.remove('conactive')
}
}
addTab() {
that.clearClass()
var li = '<li class="liactive"><span>新选项卡' + (++cnt) + '</span><span class="iconfont icon-guanbi"></span></li>'
var section = '<section class="conactive">测试' + (++cnt) + '</section>'
that.ul.insertAdjacentHTML('beforeend', li)
that.fsection.insertAdjacentHTML('beforeend', section)
that.init()
}
removeTab(e) {
// 阻止冒泡 防止触发li的切换点击事件
e.stopPropagation()
var index = this.parentNode.index
that.lis[index].remove()
that.sections[index].remove()
// console.log(index)
that.init()
if(document.querySelector('.liactive')) {
return
}
index--
// 手动调用我们的点击事件 不需要鼠标触发
that.lis[index] && that.lis[index].click()
}
editTab() {
var str = this.innerHTML
// 双击禁止选定文字
// window.getSelection(),返回一个Selection对象,表示用户选择的文本范围或光标的当前位置
// removeAllRanges将所有的区域都从选区中移除。
// document.selection.empty() 让选中的内容不选中
window.getSelection ? window.getSelection().removeAllRanges():document.selection.empty()
this.innerHTML = '<input type="text">'
var input = this.children[0]
input.value = str
// 文本框里面的文字处于选定状态
input.select()
// 当一个元素失去焦点时会触发blur事件
input.onblur = function () {
this.parentNode.innerHTML = this.value
}
// 按下回车也可以把文本框里面的值给span
input.onkeyup = function (e) {
if(e.keyCode === 13) {
// 手动调用表单失去焦点事件 不需要鼠标离开操作
this.blur()
}
}
}
}
var tab = new Tab('#tab')
构造函数和原型
实例成员
实例成员就是构造函数内部通过this添加的成员 如下列代码中uname age sing 就是实例成员,实例成员只能通过实例化的对象来访问
静态成员
在构造函数本身上添加的成员 如下列代码中 sex 就是静态成员,静态成员只能通过构造函数来访问
构造函数的问题
构造函数原型 prototype
对象原型 proto
constructor 构造函数
构造函数、实例、原型对象三者之间的关系
1.构造函数的prototype属性指向了构造函数原型对象
2.实例对象是由构造函数创建的,实例对象的__proto__属性指向了构造函数的原型对象
3.构造函数的原型对象的constructor属性指向了构造函数,实例对象的原型的constructor属性也指向了构造函数
原型链
JavaScript 的成员查找机制(规则)
原型对象this指向
构造函数中的this和原型对象的this,都指向我们new出来的实例对象
扩展内置对象
可以通过原型对象,对原来的内置对象进行扩展自定义的方法。比如给数组增加自定义求偶数和的功能。
注意:数组和字符串内置对象不能给原型对象覆盖操作 Array.prototype = {} ,只能是 Array.prototype.xxx = function(){} 的方式。
继承
ES6之前并没有给我们提供 extends 继承。我们可以通过构造函数+原型对象模拟实现继承,被称为组合继承。
call()
借用构造函数继承父类型属性
- 先定义一个父构造函数
- 再定义一个子构造函数
- 子构造函数继承父构造函数的属性(使用call方法)
借用原型对象继承父类型方法
// 1. 父构造函数
function Father(uname, age) {
// this 指向父构造函数的对象实例
this.uname = uname;
this.age = age;
}
Father.prototype.money = function() {
console.log(100000);
};
// 2 .子构造函数
function Son(uname, age, score) {
// this 指向子构造函数的对象实例
Father.call(this, uname, age);
this.score = score;
}
// Son.prototype = Father.prototype; 这样直接赋值会有问题,如果修改了子原型对象,父原型对象也会跟着一起变化
Son.prototype = new Father();
// 如果利用对象的形式修改了原型对象,别忘了利用constructor 指回原来的构造函数
Son.prototype.constructor = Son;
// 这个是子构造函数专门的方法
Son.prototype.exam = function() {
console.log('孩子要考试');
}
var son = new Son('刘德华', 18, 100);
console.log(son);
ES5 中的新增方法
数组方法
forEach()遍历数组
相当于数组遍历的 for循环 没有返回值
filter()过滤数组
some()
some和forEach区别
- 如果查询数组中唯一的元素, 用some方法更合适,在some 里面 遇到 return true 就是终止遍历 迭代效率更高
- 在forEach 里面 return 不会终止迭代
some和filter区别
同上,在filter里面 return 不会终止迭代
查询商品案例
html
<!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="./practice6.css">
</head>
<body>
<div class="search">
按照价格查询:
<input type="text" class="start"> -
<input type="text" class="end">
<button class="search-price">搜索</button> 按照商品名称查询:
<input type="text" class="product">
<button class="search-pro">查询</button>
</div>
<table>
<thead>
<tr>
<th>id</th>
<th>产品名称</th>
<th>价格</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<script>
var data = [{
id: 1,
pname: '小米',
price: 3999
}, {
id: 2,
pname: 'oppo',
price: 999
}, {
id: 3,
pname: '荣耀',
price: 1299
}, {
id: 4,
pname: '华为',
price: 1999
}, ]
var tbody = document.querySelector('tbody')
var search_price = document.querySelector('.search-price')
var start = document.querySelector('.start')
var end = document.querySelector('.end')
var product = document.querySelector('.product')
var search_pro = document.querySelector('.search-pro')
setData(data)
function setData (mydata) {
tbody.innerHTML = ''
mydata.forEach(function(value) {
// 创建一个tr节点
var tr = document.createElement('tr')
// document.createElement()是在对象中创建一个对象,要与appendChild() 或 insertBefore()方法联合使用。其中,appendChild() 方法在节点的子节点列表末添加新的子节点。insertBefore() 方法在节点的子节点列表任意位置插入新的节点。
tr.innerHTML = '<td>' + value.id + '</td><td>' + value.pname + '</td><td>' + value.price + '</td>'
tbody.appendChild(tr)
})
}
search_price.addEventListener('click', function() {
var newData = data.filter(function(value) {
return value.price >= start.value && value.price <= end.value
})
setData(newData)
})
search_pro.addEventListener('click', function() {
var arr = []
data.some(function (value) {
if(value.pname === product.value) {
arr.push(value)
return true
}
})
setData(arr)
})
</script>
</body>
</html>
css
table {
width: 600px;
border: 1px solid #000;
border-collapse: collapse;
margin-left: 214px;
}
td,
th {
border: 1px solid #000;
text-align: center;
}
input {
width: 50px;
}
.search {
width: 800px;
margin: 30px auto;
}
字符串方法trim()
对象方法
Object.keys()
Object.defineProperty()
函数的定义和调用
函数的定义方式
函数的调用方式
this
函数内 this 的指向
改变函数内部 this 指向
JavaScript 为我们专门提供了一些函数方法来帮我们更优雅的处理函数内部 this 的指向问题,常用的有 bind()、
call()、apply() 三种方法。
call 方法
apply 方法
bind 方法
call apply bind 总结
严格模式
开启严格模式
严格模式可以应用到整个脚本或个别函数中。因此在使用时,我们可以将严格模式分为为脚本开启严格模式和为函数开启严格模式两种情况。
为脚本开启严格模式
有的 script 脚本是严格模式,有的 script 脚本是正常模式,这样不利于文件合并,所以可以将整个脚本文件放在一个立即执行的匿名函数之中。这样独立创建一个作用域而不影响其他script 脚本文件。
为函数开启严格模式
严格模式中的变化
变量规定
严格模式下 this 指向问题
函数变化
高阶函数
高阶函数是对其他函数进行操作的函数,它接收函数作为参数或将函数作为返回值输出。
闭包
闭包的作用
作用:延伸变量的作用范围
<script>
function fn() {
var num = 10
function fun() {
console.log(num)
}
return fun
}
var f = fn()
f()
</script>
闭包的案例
点击 li 输出当前索引号
1、动态添加属性方式
<!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="./practice6.css">
</head>
<body>
<ul class="nav">
<li>番茄</li>
<li>羊肉串</li>
<li>基围虾</li>
<li>牛排</li>
</ul>
<script>
var lis = document.querySelector('.nav').querySelectorAll('li')
for (var i = 0 ; i < lis.length; i++) {
lis[i].index = i
lis[i].onclick = function() {
console.log(this.index);
}
}
</script>
</body>
</html>
2、利用闭包的方式得到当前 li 的索引号
for (var i = 0; i < lis.length; i++) {
// 利用for循环创建了4个立即执行函数
// 立即执行函数也成为小闭包因为立即执行函数里面的任何一个函数都可以使用它的i这变量
(function(i) {
lis[i].onclick = function() {
console.log(i);
}
})(i);
}
3秒钟之后,打印所有 li 元素的内容
for (var i = 0; i < lis.length; i++) {
(function(i) {
setTimeout(function() {
console.log(lis[i].innerHTML);
}, 3000)
})(i);
}
计算打车价格
/*需求分析
打车起步价13(3公里内), 之后每多一公里增加 5块钱. 用户输入公里数就可以计算打车价格
如果有拥堵情况,总价格多收取10块钱拥堵费*/
var car = (function() {
var start = 13; // 起步价 局部变量
var total = 0; // 总价 局部变量
return {
// 正常的总价
price: function(n) {
if (n <= 3) {
total = start;
} else {
total = start + (n - 3) * 5
}
return total;
},
// 拥堵之后的费用
yd: function(flag) {
return flag ? total + 10 : total;
}
}
})();
console.log(car.price(5)); // 23
console.log(car.yd(true)); // 33
涉及知识点:Javascript中调用对象内函数的两种方式
var cal = {
plus:function(x,y){
return x + y;
},
reduce:function(x,y){
return x - y;
},
multiply:function(x,y){
return x * y;
},
divide:function(x,y){
return x / y;
}
}
思考题
1、
var name = "The Window";
var object = {
name: "My Object",
getNameFunc: function() {
return function() {
return this.name;
};
}
};
console.log(object.getNameFunc()())
2、
var name = "The Window";
var object = {
name: "My Object",
getNameFunc: function() {
var that = this;
return function() {
return that.name;
};
}
};
console.log(object.getNameFunc()())
递归
利用递归求阶乘、斐波那契数列、递归遍历数据
<!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="./practice6.css">
</head>
<body>
<script>
function fn(start, end, sum) {
if(start > end) {
return sum
}
sum *= start
start++
return fn(start, end, sum)
}
console.log(fn(1, 5, 1));
function fun(n) {
if (n == 1) {
return 1
}
return n * fun(n - 1)
}
console.log(fun(3));
</script>
</body>
</html>
// 利用递归函数求斐波那契数列(兔子序列) 1、1、2、3、5、8、13、21...
// 用户输入一个数字 n 就可以求出 这个数字对应的兔子序列值
// 我们只需要知道用户输入的n 的前面两项(n-1 n-2)就可以计算出n 对应的序列值
function fb(n) {
if (n === 1 || n === 2) {
return 1;
}
return fb(n - 1) + fb(n - 2);
}
console.log(fb(3));
<!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="./practice6.css">
</head>
<body>
<script>
var data = [
{
id: 1,
name: '家电',
goods: [
{
id: 11,
gname: '冰箱',
goods: [
{
id: 111,
gname: '海尔'
},
{
id: 112,
gname: '美的'
},
]
},
{
id: 12,
gname: '洗衣机'
}]
},
{
id: 2,
name: '服饰'
}
];
function getID(arr, id) {
arr.forEach(function(item) {
// console.log(item);
if(item.id == id) {
console.log(item);
}
else if(item.goods && item.goods.length > 0) {
getID(item.goods, id)
}
})
}
console.log(getID(data, 11));
</script>
</body>
</html>
<!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="./practice6.css">
</head>
<body>
<script>
var data = [
{
id: 1,
name: '家电',
goods: [
{
id: 11,
gname: '冰箱',
goods: [
{
id: 111,
gname: '海尔'
},
{
id: 112,
gname: '美的'
},
]
},
{
id: 12,
gname: '洗衣机'
}]
},
{
id: 2,
name: '服饰'
}
];
function getID(arr, id) {
var obj = {}
arr.forEach(function(item) {
// console.log(item);
if(item.id == id) {
obj = item
return item
}
else if(item.goods && item.goods.length > 0) {
obj = getID(item.goods, id)
}
})
return obj
}
console.log(getID(data, 11));
</script>
</body>
</html>
浅拷贝和深拷贝
浅拷贝
<script>
var obj = {
id: 1,
name: 'Rihood',
msg: {
age: 18
}
}
var obj2 = {}
for (var k in obj) {
obj2[k] = obj[k]
}
console.log(obj2);
obj2.msg.age = 21
console.log(obj);
</script>
<script>
var obj = {
id: 1,
name: 'Rihood',
msg: {
age: 18
}
}
var obj2 = {}
for (var k in obj) {
obj2[k] = obj[k]
}
console.log(obj2);
obj2.msg.age = 21
console.log(obj);
console.log('-------------------------');
Object.assign(obj, obj2)
console.log(obj2);
</script>
深拷贝
<script>
var obj = {
id: 1,
name: 'Rihood',
msg: {
age: 18
},
color: ['red', 'navy', 'yellow']
}
var obj2 = {}
function deepCopy (newobj, oldobj) {
for (var k in oldobj) {
var item = oldobj[k]
if(item instanceof Array) {
newobj[k] = []
deepCopy(newobj[k], item)
}
else if(item instanceof Object) {
newobj[k] = {}
deepCopy(newobj[k], item)
}
else {
newobj[k] = item
}
}
}
deepCopy(obj2, obj)
console.log(obj2);
obj2.msg.age = 21
console.log(obj);
</script>
正则表达式
正则表达式( Regular Expression )是用于匹配字符串中字符组合的模式。在JavaScript中,正则表达式也是对象。
正则表通常被用来检索、替换那些符合某个模式(规则)的文本,例如验证表单:用户名表单只能输入英文字母、数字或者下划线, 昵称输入框中可以输入中文(匹配)。此外,正则表达式还常用于过滤掉页面内容中的一些敏感词(替换),或从字符串中获取我们想要的特定部分(提取)等 。
本篇博客我们主要是利用JavaScript 正则表达式完成表单验证。
创建正则表达式
测试正则表达式 test
正则表达式的组成
边界符
字符类
字符类表示有一系列字符可供选择,只要匹配其中一个就可以了。所有可供选择的字符都放在方括号内。
[ ] 方括号
[-] 方括号内部 范围符-
[ ^ ] 方括号内部 取反符^
字符组合
var rg = /[abc]/; // 只要包含有a 或者 包含有b 或者包含有c 都返回为true
console.log(rg.test('andy'));//true
console.log(rg.test('baby'));//true
console.log(rg.test('color'));//true
console.log(rg.test('red'));//false
var rg1 = /^[abc]$/; // 三选一 只有是a 或者是 b 或者是c 这三个字母才返回 true
console.log(rg1.test('aa'));//false
console.log(rg1.test('a'));//true
console.log(rg1.test('b'));//true
console.log(rg1.test('c'));//true
console.log(rg1.test('abc'));//false
----------------------------------------------------------------------------------
var reg = /^[a-z]$/ //26个英文字母任何一个字母返回 true - 表示的是a 到z 的范围
console.log(reg.test('a'));//true
console.log(reg.test('z'));//true
console.log(reg.test('A'));//false
-----------------------------------------------------------------------------------
//字符组合
var reg1 = /^[a-zA-Z0-9]$/; // 26个英文字母(大写和小写都可以)任何一个字母返回 true
------------------------------------------------------------------------------------
//取反 方括号内部加上 ^ 表示取反,只要包含方括号内的字符,都返回 false 。
var reg2 = /^[^a-zA-Z0-9]$/;
console.log(reg2.test('a'));//false
console.log(reg2.test('B'));//false
console.log(reg2.test(8));//false
console.log(reg2.test('!'));//true
量词符
用户名验证小案例
html
<!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="./practice6.css">
</head>
<body>
<input type="text" class="uname"> <span>请输入用户名</span>
<script>
var reg = /^[a-zA-Z0-9_-]{6,16}$/
var uname = document.querySelector('.uname')
var span = document.querySelector('span')
uname.onblur = function () {
if (reg.test(this.value)) {
span.className = 'right'
span.innerHTML = '用户名格式输入正确'
}
else {
span.className = 'wrong'
span.innerHTML = '用户名格式输入错误'
}
}
</script>
</body>
</html>
css
span {
color: #aaa;
font-size: 14px;
}
.right {
color: green;
}
.wrong {
color: red;
}
括号总结
预定义类
验证座机号码小案例
表单验证小案例
//手机号验证:/^1[3|4|5|7|8][0-9]{9}$/;
//验证通过与不通过更换元素的类名与元素中的内容
if (reg.test(this.value)) {
// console.log('正确的');
this.nextElementSibling.className = 'success';
this.nextElementSibling.innerHTML = '<i class="success_icon"></i> 恭喜您输入正确';
} else {
// console.log('不正确');
this.nextElementSibling.className = 'error';
this.nextElementSibling.innerHTML = '<i class="error_icon"></i>格式不正确,请从新输入 ';
}
//QQ号验证: /^[1-9]\d{4,}$/;
//昵称验证:/^[\u4e00-\u9fa5]{2,8}$/
//验证通过与不通过更换元素的类名与元素中的内容 ,将上一步的匹配代码进行封装,多次调用即可
function regexp(ele, reg) {
ele.onblur = function() {
if (reg.test(this.value)) {
// console.log('正确的');
this.nextElementSibling.className = 'success';
this.nextElementSibling.innerHTML = '<i class="success_icon"></i> 恭喜您输入正确';
} else {
// console.log('不正确');
this.nextElementSibling.className = 'error';
this.nextElementSibling.innerHTML = '<i class="error_icon"></i> 格式不正确,请从新输入 ';
}
}
};
正则表达式中的替换
replace 替换
正则表达式参数
过滤敏感词汇小案例
<textarea name="" id="message"></textarea> <button>提交</button>
<div></div>
<script>
var text = document.querySelector('textarea');
var btn = document.querySelector('button');
var div = document.querySelector('div');
btn.onclick = function() {
div.innerHTML = text.value.replace(/激情|gay/g, '**');
}
</script>
ES6
ES6 的新增语法
默认参数
let(★★★)
经典面试题
const(★★★)
let、const、var 的区别
解构赋值(★★★)
数组解构
对象解构
箭头函数(★★★)
const obj = { name: '张三'}
function fn () {
console.log(this);//this 指向 是obj对象
return () => {
console.log(this);//this 指向 的是箭头函数定义的位置,那么这个箭头函数定义在fn里面,而这个fn指向是的obj对象,所以这个this也指向是obj对象
}
}
const resFn = fn.call(obj);
resFn();
小结
- 箭头函数中不绑定this,箭头函数中的this指向是它所定义的位置,可以简单理解成,定义箭头函数中的作用域的this指向谁,它就指向谁
- 箭头函数的优点在于解决了this执行环境所造成的一些问题。比如:解决了匿名函数this指向的问题(匿名函数的执行环境具有全局性),包括setTimeout和setInterval中使用this所造成的问题
面试题
var age = 100;
var obj = {
age: 20,
say: () => {
alert(this.age)
}
}
obj.say();//箭头函数this指向的是被声明的作用域里面,而对象没有作用域的,所以箭头函数虽然在对象中被定义,但是this指向的是全局作用域
剩余参数(★★)
这种方式很方便的去声明不知道参数情况下的一个函数
剩余参数和解构配合使用
ES6 的内置对象扩展
Array 的扩展方法(★★)
扩展运算符(展开语法)
扩展运算符可以应用于合并数组
将类数组或可遍历对象转换为真正的数组
<!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="./practice6.css">
</head>
<body>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<script>
var oDivs = document.querySelectorAll('div')
console.log(oDivs);
oDivs = [...oDivs]
console.log(oDivs);
</script>
</body>
</html>
构造函数方法:Array.from()
方法还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理,将处理后的值放入返回的数组
注意:如果是对象,那么属性需要写对应的索引
实例方法:find()
实例方法:findIndex()
实例方法:includes()
String 的扩展方法
模板字符串(★★★)
实例方法:startsWith() 和 endsWith()
实例方法:repeat()
Set 数据结构(★★)
实例方法
遍历
如果喜欢我的文章,请记得一键三连哦,点赞关注收藏,你的每一个赞每一份关注每一次收藏都将是我前进路上的无限动力 !!!↖(▔▽▔)↗感谢支持,明天我们不见不散!!!
网盘资源(仅供学习使用,不可商用!!!)
1、2021年黑马-368集课程成就一名前端开发高手:
链接: https://pan.baidu.com/s/1lJ60x1tH7r0wLYyrvFxivg?pwd=f1kc 提取码: f1kc 复制这段内容后打开百度网盘手机App,操作更方便哦
–来自百度网盘超级会员v3的分享
2、2022最新版黑马程序员前端学习路线图:
链接: https://pan.baidu.com/s/1BvWHQ2bnfUNycw5RzRoewQ?pwd=5kjf 提取码: 5kjf 复制这段内容后打开百度网盘手机App,操作更方便哦
–来自百度网盘超级会员v3的分享