复习
-
函数的this
- 基础设定: 函数放在哪个对象里执行, 其this关键词就代码这个对象
- call:
短暂访问
- 把函数临时放到对象里运行, 运行完毕后自动删除 - apply: 把函数临时放到对象里执行, 实参要
打包--数组模式
传递- 有了此方法, 才能把数组 拆分成1个1个值 的方式传递给函数
- ES6中: 提供了 展开符
...
可以轻松的打散数组, 展开数组
- bind: 把 对象和实参 与函数捆绑在一起, 返回一个新的函数 –
不会立即触发
- 适合: 延时触发的场景 – 与DOM的事件 (
点击事件
) 绑定
- 适合: 延时触发的场景 – 与DOM的事件 (
-
构造函数: 用于构建创造对象的函数 –
程序员必须具备的能力
-
原型理论:
- 共享的函数, 要存放在 prototype 属性里
- 生成对象时, 利用其
__proto__
属性关联到 prototype 对象
-
原型链机制:
__proto__
- 当读取对象的属性时, 如果对象本身没有, 会自动到其
__proto__
关联的对象里找
- 当读取对象的属性时, 如果对象本身没有, 会自动到其
-
new运算符: 配合构造函数使用, 可以简化3行代码
var this = {} this.__proto__ = 函数.prototype return this
-
class语法: 全自动完成原型操作
class 类{ // 固定名称: 在new时触发 constructor(x,y){ this.x = x this.y = y } 函数(){} 函数(){} }
-
-
严格模式
- 在严格模式下, JS将会提供更多的报错信息
- 开启方式: 在脚本开头书写
'use strict'
类class
类中各种属性的用途
<!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>静态属性语法 09:20</title>
</head>
<body>
<script>
// 对象创建有两种方式:
// 1.构造方式: 先制作一个构造函数, 然后通过构造函数来创建对象 -- 适合重复使用
// 2.直接书写对象类型 -- 适合一次性
// JS代码:
var emp = { ename: '泡泡', age: 18 }
console.log(emp.ename, emp.age)
console.log(emp)
// class语法中制作不需要new 就能用的对象: 静态属性
class Emp1 {
// static: 静态 - 直接存储在类中, 能直接 类名.属性名
static name = '泡泡'
static age = 18
}
console.log(Emp1.age, Emp1.name)
console.dir(Emp1)
</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>继承 09:42</title>
</head>
<body>
<script>
// 面向对象的三大特征: 封装 继承 多态
// 封装: 用{}把很多代码括起来, 起个名字, 以后能复用
// 继承: 子类可以继承父类的所有属性, 为类提供了丰富的可扩展性
// 多态: 子类通过重写, 可以让同样的方法名出现不同状态的表现
// -- 一代更比一代强
class Father {
constructor(name, money) {
this.name = name
this.money = money
}
eat() {
console.log('爱吃萝卜爱吃菜')
}
}
// extends: 继承; 代表 Son 继承了 Father 所有的内容
class Son extends Father {
// 重写: 对父传递的方法, 可以重写
eat() {
super.eat() // super: 代表父, 调用父的eat
console.log('两只耳朵竖起来')
}
play() {
console.log('孙尚香 蔡文姬 瑶 都很6')
}
}
var s1 = new Son('小亮', 500)
console.dir(s1) //查看其 prototype 原型
s1.eat()
s1.play()
</script>
</body>
</html>
ES6
<!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>ES6 10:24</title>
</head>
<body>
<!--
JS的重大升级版本: ES6 -- 2015年6月
- ES6 : 即特征 第6个版本, 也 泛指ES6后续新增的所有版本
文档: https://es6.ruanyifeng.com/
-->
</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>作用域 10:30</title>
</head>
<body>
<script>
// ES6版本中, 推出了新增的作用域: 脚本作用域 和 块级作用域
// 全局作用域: window对象, 用于存放系统API
// 问题: 利用 var 或 function 在脚本中声明的变量, 会自动存储在 全局对象, 造成全局污染 -- 以前如何解决?
// 以前: 用匿名函数自调用语法, 快速生成局部作用域来存
// ES6中提供了两个新的关键词, 用于声明变量 let const
// var 和 let 都能声明变量, 但是存储的位置不同
var a = 10 //存放在window里, 有全局污染
// 存储在新增的 脚本作用域 -- 必须利用断点技术才能看到
// 脚本作用域 和 全局的window相同: 有 且 只有1个
let b = 20 //不存在污染
console.log(window)
// let 不允许重复声明, 会报错
var c = 10
// let c = 20
</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>块级作用域 10:46</title>
</head>
<body>
<script>
// ES6中, 用 let 或 const 搭配 {} 使用, 自动形成块级作用域, 代替 繁琐的函数作用域
{
let a = 10
console.log(111)
}
// 用let声明, 配合for的{}, 会自然形成块级作用域
for (let i = 0; i < 10; i++) {
console.log(i)
}
// 还有哪些语法 的 {} 能配合出块级?
// if
// while do...while
// switch
// 注意:
// function的{} 是 局部作用域, 不会被let改成块级
// 在函数的{}里, 用let 和 var 没有区别
// 对象中, 没有书写let的语法
// var emp = {name:"泡泡", let age = "33"}
console.log(window)
// 函数以后不推荐用: 会存放在全局中
function xx() {}
// 推荐: yy存放在脚本作用域
const yy = function () {}
</script>
</body>
</html>
let_const
<!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>let与const 11:23</title>
</head>
<body>
<script>
// let: 声明变量 -- 后续可修改值
// const: 声明常量 -- 初始化赋值后 不可修改; 更安全
// 变量到底用哪个声明, 要根据实际情况来选择
// 世宇的薪资 salary
let salary = 7000
salary = 8000
// 世宇的妻子 wife
const wife = '翠花'
wife = '泡泡'
// const:安全可靠. 在不可变时, 用const
// 对象类型是引用类型, 地址不变, 但是内容可以改
const girl = { ename: '泡泡', age: 18 }
girl.age = 20
</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>声明提升 11:31</title>
</head>
<body>
<script>
// let和const 是否存在声明提升?
// 声明提升是 JS引擎的祖传设定, 无法修改
// 一旦修改 会导致之前20多年用到JS的项目报错, 无法运行
// 事实证明: 声明提升不是一个好的设计, 不应该让用户书写
// 通过报错来解决
console.log(111)
// 报错: 无法访问a 在其声明代码运行之前
// 这种状态称为 `暂存死区`: 提升后处于锁死的状态, 必须在声明行代码执行后才能激活
console.log(a)
let a = 1
const b = 2
// 不推荐再使用var和function: 因为存在声明提升的问题
</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>模板字符串 11:45</title>
</head>
<body>
<ul id="box"></ul>
<script>
// 随着时代的发展, JS 和 HTML 的互动越来越多
// 特别是 AJAX 流行起来之后, 把网络请求到的数据 转换成 HTML 代码, 此时用 `+` 做字符串拼接 会非常复杂
const names = ['泡泡', '亮亮', '铭铭', '小新']
// const str = '<li>'+names[0]+'</li><li>'+names[1]+'</li><li>'+names[2]+'</li><li>'+names[3]+'</li>'
// 模板字符串: `` 配合 ${} 使用, 支持换行
// 模板: 对 HTML的另一种称呼 -- 文档
// 所以: 模板字符串是专为 JS中书写 HTML代码而生的, 确保了格式更加易读
const str = `
<li>${names[0]}</li>
<li>${names[1]}</li>
<li>${names[2]}</li>
<li>${names[3]}</li>
`
box.innerHTML = str
</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>箭头函数 14:01</title>
</head>
<body>
<script>
// ES6提供了新的函数语法: 箭头函数
// 之前: function(){}
// 箭头: ()=>{} -- 简化函数的书写
// 提供 两个语法糖
const show = function (x) {
return x * 2
}
// 糖1: 形参只有1个时, 其() 可以省略
const show1 = x => {
return x * 2
}
// 糖2: 函数体中仅有1行代码时, 可以省略 { return }
const show2 = x => x * 2
// 练习: 把下方代码 改成简化语法
const show3 = y => y + 3
const show4 = (x, y) => x + y
// 坑: 如果返回值是对象类型, 其{} 会被错误的识别为 函数的{}
// 用 () 包围, 来解决冲突
const show5 = (x, y) => ({ x: x, y: y })
// {属性名: 值}, 如果值是变量, 恰好 变量名和属性名一样, 则可以合并 {x: x} -> { x }
const show6 = (x, y) => ({ x, y })
</script>
</body>
</html>
this
<!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>箭头函数的this 14:26</title>
</head>
<body>
<script>
// this: 由于作者在多个场景中, 都使用到了此关键词, 需要根据具体场景来分辨用途
// function在如下语法中, this 是什么意思?
// 函数() : 没有前缀对象, 则指向window
// -- 严格模式下, 是undefined
// 对象.函数(): 函数所在对象
// new 函数(): 构造出来的对象 , 实例对象
//
// 箭头函数没有this关键词
// - 会按照作用域链原则, 到上级作用域查找
// 因为箭头函数没有自己的this
// 所以: 不能作为构造函数使用. 没有call bind apply 方法
// this 声明时所在作用域有关, 和所在对象无关
const show = () => console.log(this)
console.log(this) //全局区
show()
//
const emp = {
ename: '泡泡',
// :function 可以省略不写
// marry: function () {},
marry() {
console.log(this, '结婚啦')
const show = () => {
// 箭头函数内部没有this变量, 按照作用域链的元素到上层作用域 -- marry() 函数作用域中查找使用
console.log('this:', this)
}
show()
},
}
emp.marry()
</script>
</body>
</html>
every
<!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>数组的高阶函数 every 15:06</title>
</head>
<body>
<script>
// 以后工作的主要场景: 通过AJAX从服务器获取数据, 获取的数据都是通过数据库查询到的, 基本都是数组类型
// 把数组转为HTML 属于日常操作
// 高阶函数: 函数中使用了其他函数, 就叫高阶函数
// every: 每个, 每一个
console.log(Array.prototype)
var nums = [12, 43, 45, 65, 87, 98, 4]
// 任务: 判断数组里 每个元素 是否都是正数
// 值 序号 数组
var x = nums.every((value, index, array) => {
console.log(
`当前检测:${value}, 序号:${index}, 来自:${array}`
)
//返回检测结果: true代表通过 false代表不通过
// return true //通过: 就会继续检测下一个
if (value > 0) {
return true
} else {
return false
}
})
console.log('x:', x) // 只要有一个元素 不通过, 整个验证结果是假的
console.log(x ? '都是正数' : '非都是正的')
</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>练习 15:36</title>
</head>
<body>
<script>
var nums = [123, 435, 45, 234, 67, 567]
// 判断是否每个元素都大于60
var x = nums.every((value, index, array) => {
return value > 60
// if (value > 60) {
// return true
// } else {
// return false
// }
})
// 可以把没用到的形参,省略不写 -- 仅限最后面的
var x = nums.every((value, index, array) => value > 60)
// 最终:
var x = nums.every(value => value > 60)
console.log(x ? '都大于60' : '非都大于60')
// 判断数组中是否都是偶数: 对2 取余结果是0
var x = nums.every(value => value % 2 == 0)
console.log(x ? '都是偶数' : '非都是偶数')
</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>练习 15:55</title>
</head>
<body>
<script>
var emps = [
{ name: '泡泡1', married: false, age: 28 },
{ name: '泡泡2', married: true, age: 38 },
{ name: '泡泡3', married: false, age: 18 },
{ name: '泡泡4', married: true, age: 38 },
{ name: '泡泡5', married: false, age: 58 },
]
// 1. 判断是否每个人都已婚
var x = emps.every(emp => emp.married)
console.log(x ? '都已婚' : '非都已婚')
// 2. 判断是否每个人都大于20岁
var x = emps.every(emp => emp.age > 20)
console.log(x ? '都大于20' : '非都大于20')
// 类似于 : 逻辑与 && 都是真的才是真
</script>
</body>
</html>
some
<!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>some 16:26</title>
</head>
<body>
<script>
// some: 一些, 至少有一个
var nums = [12, 32, 4, 6, -76, 87, 5]
// 判断是否存在负数
var x = nums.some((value, index, array) => {
return value < 0
})
var x = nums.some(v => v < 0)
// 自动遍历数组, 对元素判断, 有一个是真, 结果就是真
console.log(x ? '有负数' : '没有负数')
var emps = [
{ name: '泡泡1', salary: 9000 },
{ name: '泡泡2', salary: 19000 },
{ name: '泡泡3', salary: 12000 },
{ name: '泡泡4', salary: 13000 },
]
// 判断是否有人薪资低于1W
var x = emps.some(emp => emp.salary < 10000)
console.log(x ? '存在' : '不存在')
</script>
</body>
</html>
filter
<!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>过滤器 16:38</title>
</head>
<body>
<script>
// filter: 过滤器 -- 把满足条件的元素过滤出来,组成新的数组
var nums = [12, 234, 54, 456, 2, 3, 45, 45]
// 找出所有的偶数
var x = nums.filter((value, index, array) => {
return value % 2 == 0
})
var x = nums.filter(v => v % 2 == 0)
console.log(x)
// 练习
var emps = [
{ name: '泡泡1', age: 18, salary: 9000 },
{ name: '泡泡2', age: 28, salary: 6000 },
{ name: '泡泡3', age: 22, salary: 29000 },
{ name: '泡泡4', age: 32, salary: 19000 },
{ name: '泡泡5', age: 34, salary: 23000 },
]
// 1. 找出所有年龄大于20岁的人
var x = emps.filter(emp => emp.age > 20)
console.log(x)
// 2. 找出薪资大于1W的人
var x = emps.filter(emp => emp.salary > 10000)
console.log(x)
// 3. 找出年龄小于30 但 薪资大于1W的人
var x = emps.filter(
emp => emp.age < 30 && emp.salary > 10000
)
console.log(x)
</script>
</body>
</html>
map
<!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>映射 17:14</title>
</head>
<body>
<script>
// map: 把数组中的每个元素, 修改之后, 组合成新的数组
var nums = [12, 3, 43, 54, 65, 76]
// 把每个数字 x2
var x = nums.map((value, index, array) => {
return value * 2
})
var x = nums.map(value => value * 2)
console.log(x)
</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>练习 17:21</title>
</head>
<body>
<ul id="box"></ul>
<div id="box1"></div>
<div id="box2">
<!-- 推荐: 在html中把伪代码书写出来, 再复制到JS里 -->
<!-- <img src="" alt="" /> -->
</div>
<div id="box3">
<!-- <a href=""></a> -->
</div>
<script>
var names = ['泡泡', '铭铭', '亮亮']
// 每个元素放到 li 标签里: <li>xx</li>
var x = names.map(value => `<li>${value}</li>`)
console.log(x)
// join: 把数组的元素拼接到一起, 组合成字符串
// 默认逗号间隔, 写空字符串可以去掉
box.innerHTML = x.join('')
// 练习:
var skills = ['css', 'js', 'html', 'express']
// 数据转为按钮 <button>xx</button> 放入box1
var x = skills.map(v => `<button>${v}</button>`)
box1.innerHTML = x.join('')
// 练习
var imgs = [
'https://web.codeboy.com/xuezi/img/index/banner1.png',
'https://web.codeboy.com/xuezi/img/index/banner2.png',
'https://web.codeboy.com/xuezi/img/index/banner3.png',
'https://web.codeboy.com/xuezi/img/index/banner4.png',
]
var x = imgs.map(v => `<img src="${v}" alt="" />`)
box2.innerHTML = x.join('')
// 练习:
var webs = [
{ title: '新闻', href: 'http://news.baidu.com/' },
{ title: 'hao123', href: 'http://www.hao123.com/' },
{ title: '地图', href: 'http://map.baidu.com/' },
{ title: '贴吧', href: 'http://tieba.baidu.com/' },
]
// 把数据转为 超链接 a 标签, 显示到 div#box3 里
var x = webs.map(w => `<a href="${w.href}">${w.title}</a>`)
box3.innerHTML = x.join('')
</script>
</body>
</html>
ajax
<!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>练习 17:52</title>
</head>
<body>
<div id="box">
<!-- <img src="" alt="" /> -->
</div>
<script>
// 实战: 通过请求从接口获取数据
var xhr = new XMLHttpRequest()
// https://api.xin88.top/game/items.json
xhr.open('GET', 'https://api.xin88.top/game/items.json')
xhr.send()
xhr.onload = function () {
// console.log(xhr)
var data = JSON.parse(xhr.response)
console.log(data)
var x = data.items.map(
item => `<img src="${item.iconPath}" alt="" />`
)
box.innerHTML = x.join('')
}
</script>
</body>
</html>