06-ES6特点

image-20251125100829463

ES,即ECMAScript,js语法,如ES5或ES6都是js语法发展过程中发布的版本。

浏览器会去跟进发布新版本,来支持,比如ES6等。

兼容性:对浏览器要考虑哪些是ES5或ES6的,确认浏览器是否都支持。

特性举例:

  • 模版字符串,就是ES6的其中一个功能特性

    1
    `${key}`

1. 定义变量

  • let 严格的变量定义(用法与var基本一致)
    • 必须先定义再使用
    • 变量不允许重名
    • 只在定义的作用域内生效
  • const 常量定义
    • 不允许被二次赋值

var 的问题:变量声明提升(不同作用域里是可以同名的),因为会预解析,块级作用域外也可以访问等,都是缺点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<script>
// let
//console.log(a) //ERROR: Cannot access 'a' before initialization(不能在初始化之前访问)
let a = 100
console.log(a)
//let a = 200 //ERROR: Identifier 'a' has already been declared(不能重复定义)
if (true) {
let i = 22
console.log(i) //22
}
//console.log(i) //ERROR: i is not defined

// const
const name = "jerry"
//name = "xiaoMing"
console.log(name) //ERROR: Assignment to constant variable(常量不允许被二次赋值)

// 对象类型要区分堆栈,obj不能二次赋值,但是内部的值可以修改
const obj = {
name: "jerry"
}
obj.name = "xiaoMing"
console.log(obj) // {name: "xiaoMing"}
</script>

案例:选项卡-块级作用域

改造区域:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<script>
let oHeaderLis = document.querySelectorAll(".header li")
let oBoxLis = document.querySelectorAll(".box li")
for (let i = 0; i < oHeaderLis.length; i++) {
//oHeaderLis[i].dataset.index = i
oHeaderLis[i].onclick = function() {
console.log(i) // let i 后,值就在只块级作用域,就不需要 dataset.index 临时记录了
let index = i
for (let j = 0; j < oBoxLis.length; j++) {
oHeaderLis[j].classList.remove("active")
oBoxLis[j].classList.remove("active")
}
//oHeaderLis[this.dataset.index].classList.add("active")
oHeaderLis[index].classList.add("active")
//oBoxLis[this.dataset.index].classList.add("active")
oBoxLis[index].classList.add("active")
}
}
</script>

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
*{
margin: 0;
padding: 0;
}
ul {
list-style: none;
}
.header {
display: flex;
width: 600px;
}
.header li{
flex: 1;
border: 1px solid #ccc;
height: 50px;
line-height: 50px;
text-align: center;
}
.box {
position: relative;
width: 600px;
}
.box li{
position: absolute;
left: 0;
top: 0;
width: 600px;
height: 100px;
line-height: 100px;
text-align: center;
background: yellow;

display: none;
}
.box .active{
background: yellow;
display: block;
}
.header .active {
background: red;
}
</style>
</head>
<body>
<ul class="header">
<li class="active">1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<ul class="box">
<li class="active">111</li>
<li>222</li>
<li>333</li>
<li>444</li>
<li>555</li>
</ul>

<script>
let oHeaderLis = document.querySelectorAll(".header li")
let oBoxLis = document.querySelectorAll(".box li")
for (let i = 0; i < oHeaderLis.length; i++) {
//oHeaderLis[i].dataset.index = i
oHeaderLis[i].onclick = function() {
console.log(i) // let i 后,值就在只块级作用域,就不需要 dataset.index 临时记录了
let index = i
for (let j = 0; j < oBoxLis.length; j++) {
oHeaderLis[j].classList.remove("active")
oBoxLis[j].classList.remove("active")
}
//oHeaderLis[this.dataset.index].classList.add("active")
oHeaderLis[index].classList.add("active")
//oBoxLis[this.dataset.index].classList.add("active")
oBoxLis[index].classList.add("active")
}
}
</script>
</body>
</html>

效果一样:

chrome-capture-2025-12-09 (1)

2. 箭头函数

语法:

  • () => { 代码 } 与 function() { 代码 } 功能相同
    • a => { 代码 } 只有一个形参时,( ) 可以省略
    • a => a*100 只有一句代码 或 只有返回值时,{ } 和 return 都可以省略
    • 只返回一个值对象时,箭头函数需特殊处理,将返回的对象上加小括号 ({ key: value,... })
    • 箭头函数无法使用 函数内置参数对象 arguments,需要显式的写形参 (arg1, arg2...) => {代码}
    • 箭头函数在事件绑定回调函数中通过 this 可以直接拿到事件绑定的元素对象
1
2
3
4
5
6
<script>
var test = () => {
console.log("111")
}
test() //111
</script>

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<input type="text" id="myinput">
<script>
let test1 = function() {
console.log("111111")
}
test1() //111111

// 箭头函数
let test2 = () => {
console.log("222222")
}
test2() //222222

// 一个参数时,可以省略()
let test3 = a => {
console.log("a=", a)
}
test3(10) // a=10

// 只有返回值时,可以省略{}
let test4 = a => a*100
console.log(test4(10)) // 1000

// 一个参数和一个返回值时的简洁改造
let list = ["111", "222", "333"]
let newList = list.map(item => `<li>${item}</li>`)
console.log(newList.join("")) // <li>111</li><li>222</li><li>333</li>

// 只返回一个值对象时,需特殊处理,将对象加上小括号()
let test5 = () => ({
name: "jerry",
age: 18
})
console.log(test5()) // {name: 'jerry', age: 18}

// 箭头函数无法使用 函数内置参数对象 arguments,需要显式的写形参 (arg1, arg2...) => {代码}
let test6 = function() {
console.log(arguments)
console.log(Array.from(arguments))
}
test6(1, 2, 3) // 函数内置参数对象(伪数组):Arguments(3)[1, 2, 3, ...]

myinput.oninput = function() {
// 如果是function 则需要临时存一下 this
let that = this
setTimeout(function() {
console.log("func ", that.value)
}, 1000)

// 箭头函数中 this 可以直接拿到当前事件绑定元素对象
setTimeout(() => {
console.log("=> ", this.value)
}, 1000)
}

// 函数默认参数
let test7 = (a=1, b=2) => a+b
console.log(test7(10, 20))
console.log(test7()) // 万一忘记传参时,可以使用默认参数
</script>

3. 解构赋值

解构赋值,快速的从对象和数组中获取里面的成员。

  • 数组/多维数组:[ ] 对号入座
  • 对象/复杂对象:{ } key值对号入座,如果key值涉及重命名则通过 旧名字:新名字 重命名
    • 复杂对象,拷贝结构,保留key,删掉值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<script>
// 解构赋值
let arr = ["aaa", "bbb", "ccc"]
let [x, y, z] = arr
console.log(x, y, z) //aaa bbb ccc

// 案例:交换两个数,此时只能用 var 可以重名定义
var a = 10
var b = 20
var [a, b] = [b, a]
console.log(a, b) //20 10

// 案例:多维数组解构
let arr2 = [1, 2, [3, 4, [5]]]
console.log(arr2[2][2][0]) //5
let [q, w, [e, r, [t]]] = arr2
console.log(t) //5

// 对象解构赋值 - 最有用
let obj = {
name: "jerry",
age: 18,
location: "china" // 前端是关键字,后端不愿意更改,就可以进行解构时重命名
}
// 对象中的属性解构赋值时,名字需要一样;如果名字无法更改,可以冒号 :新名字 进行重命名
let {name, age, location:location0} = obj
console.log(name, age, location0) // jerry 18 china

// 复杂对象解构赋值:拷贝结构,保留key删掉值
let obj2 = {
name2: "jerry",
age2: 20,
location2: {
province2: "henan",
city2: "nanyang"
},
hobby2: [111, 222, 333]
}
let {
name2,
age2,
location2: {
province2,
city2
},
hobby2: [m, n, k]
} = obj2
console.log(name2, age2, province2, city2, m, n, k) // jerry 20 henan nanyang 111 222 333
</script>

4. 对象简写

  • 当对象的key值与变量定义一样时,就可以简写为只有key,如 let obj = {username, password}
  • 对象中的方法 getName: function() {}可以简写为 getName() {}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<input type="text" id="myUsername">
<input type="password" id="myPassword">
<button id="myBtn">登陆</button>
<script>
myBtn.onclick = () => {
let username = myUsername.value
let password = myPassword.value
console.log(username, password)
// 对象的key值与变量定义一样时,就可以简写为只有key
let obj = {
//username: username,
username,
//password: password
password
}
console.log("发送给后端的结构:", obj)
}

let obj1 = {
name: "jerry",
//getName: function() {
getName() { // 简写方式
console.log(this.name)
}
}
obj1.getName() // jerry
</script>

5. 展开运算符

... 展开运算,可用在不同的场景。

  • 展开数组赋值
  • 复制数组,深拷贝效果
  • 展开形参,必须作为最后一个形参或者独立参数,接收剩余参数
  • 展开实参,解构传入实参
  • 展开对象,合并对象key-value,同名会 后覆盖前(在处理修改字段提交给后端时很实用 - 如示例代码)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
<ul>
<li>111</li>
<li>222</li>
<li>333</li>
<li>444</li>
<li>555</li>
</ul>
<h3>修改</h3>
名字:<input type="text" id="myUsername">
<br>
年龄:<input type="text" id="myAge">
<br>
<input type="button" value="修改" id="btn">
<div id="box"></div>
<script>
// ...展开数组
let a = [1, 2, 3]
let b = [4, 5, 6]
console.log(a.concat(b)) // [1, 2, 3, 4, 5, 6]
let c = [a, b]
console.log(c) // [Array(3), Array(3)]
let c1 = [...a, ...b]
console.log(c1) // [1, 2, 3, 4, 5, 6]

// ...复制(深拷贝)
let a1 = [1, 2, 3]
let b1 = [...a1] // 展开数组,会重新创建新数组,不影响原数据
b1[0] = "jerry"
console.log(b1) // ['jerry', 2, 3]

// ...参数-形参: 必须作为最后一个形参,接收剩余参数
let func = (a, b, ...arr) => {
console.log(a, b) // 1 2
console.log(arr) // [3, 4, 5]
}
func(1, 2, 3, 4, 5)

// ...参数-实参:解构传入实参
let arr = [1, 2, 3]
let func1 = (a, b, c) => {
console.log(a, b, c) //1 2 3
}
func1(...arr)

let arr1 = [11, 55, 22, 66, 33]
let max = Math.max(...arr1)
console.log(max) // 66

// ...伪数组转换: function 中可以用 arguments,用 ... 解构出参数为数组
function func2() {
let arr = [...arguments]
console.log(arr)
}
func2(5, 4, 3)

let oliItems = document.querySelectorAll("li")
let oliArr = [...oliItems]
console.log(oliArr) // li对象数组:[li, li, li, li, li]
console.log(oliArr.filter) // native code:表示支持的方法

// ...对象:合并对象key-value,同名会 后覆盖前
let obj1 = {
name: "jerry",
age: 18
}
let obj2 = {
name: "tom",
location: "china"
}
let obj = {
...obj1,
...obj2
}
console.log(obj)


// 实例:形参中展开对象
let obj3 = {
name: "jerry",
age: 20,
location: "china",
id: "3242313412341341341"
}
function render({name, age, location}) {
box.innerHTML = `name:${name}, age:${age}, location:${location}`
}
render(obj3)

btn.onclick = () => {
// 确保未修改的字段是原值
let name = myUsername.value || obj3.name
let age = myAge.value || obj3.age

// 修改操作,合并原字段,添加新字段
let newObj = {
...obj3, // 原字段不变
name, // 修改字段,即:重名会覆盖原字段
age // 修改字段,即:重名会覆盖原字段
}
console.log(newObj)
// 传给后端
// 渲染到页面
render(newObj)
}
</script>

对象合并效果:

chrome-capture-2025-12-11

6. 模块化语法

模块化:①私密不漏重名不怕依赖不乱

条件:必须在 live server 模式下运行,否则模块化引入的js是不生效的。

模块化是一种思想。

  • export{...} js文件中导出供外部使用的方法(未导出的不能被使用)
  • import{..., func as func1, ...} from 'x.js' 页面文件中导入所需的js方法,as 可重命名
  • <script type="module"> js脚本类型限定为 module,才是模块化语法
  • 特殊:
    • export default func 导出
    • import funccc from 'x.js' 导入,不需要{}且可随意命名

示例:

./module/a.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function A1() {
a_common()
console.log("A1-布局创建")
}
function A2() {
a_common()
console.log("A2-布局创建")
}
function a_common() {
console.log("a_common")
}
function test() {
console.log("a test")
}
function A_A() {
console.log("A_A")
}
// 导出
export {
A1,
A2,
test,
A_A
}

./module/b.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function B1() {
b_common()
console.log("B1-布局创建")
}
function B2() {
b_common()
console.log("B2-布局创建")
}
function b_common() {
console.log("b_common")
}
function test() {
console.log("b test")
}
function B_B() {
console.log("B_B")
}
// 导出
export {
B1,
B2,
test,
B_B
}

./module/c.js (依赖了a.js和b.js中的方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 导入所需的依赖js
import {A_A} from './a.js'
import {B_B} from './b.js'
function c() {
A_A()
B_B()
console.log("CC")
}
// 导出
// export {
// c
// }
// 导出默认
export default c

./index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 引入并限定为 module 类型 -->
<!-- <script src="./module/c.js" type="module"></script> -->
</head>
<body>
<!-- 限定为 module 类型 -->
<script type="module">
/* 1. 从指定的js文件里,导入需要的方法 */
/* 2. as 可以对方法进行重命名,调用时使用新名称 */
import {A1, A2, test as a_test} from './module/a.js'
import {B1, B2, test as b_test} from './module/b.js'
/* 只导出一个default默认时,可以随便命名和使用,不需要{} */
import ccc from './module/c.js'

A1() // 正常调用和执行
A2() // 正常调用和执行
a_test() // 正常调用和执行
b_test() // 正常调用和执行
//a_common() // is not defined. 私密方法不允许被访问了

ccc()
</script>
</body>
</html>

7. 面向对象

7.1 创建对象

面向对象,一种思想,一种编程模式。

  • Object js给我们内置了一个构造函数,用来创建对象

遵循规范:

  1. 首字母大写
  2. 构造函数不写return
  3. 构造函数可以当成普通函数用,但是不会这么做
  4. this 指向 new 出来的实例化对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<script>
// 1.首字母大写
function CreateObj(name) {
this.name = name
}
let obj = new CreateObj("jerry")
console.log(obj) // {name: 'jerry'}

// 2.构造函数不写return
function CreateObj1(name) {
this.name = name
//return {a:1, b:2}
}
let obj1 = new CreateObj1("jerry")
console.log(obj1) // {name: 'jerry'}

// 3.构造函数可以当成普通函数用,但是不会这么做
function CreateObj2(name) {
this.name = name
}
var obj2 = CreateObj2("jerry")
console.log(obj2, window.name) // undefined 'jerry'

// this 指向:new 的实例化对象
</script>

7.2 面向对象的原型

  • prototype 原型,共享内存,且对象能够直接访问到原型上定义的方法
    • 对象.__proto__ === 构造函数.prototype
  • 原型链概念:如 obj.toString() 方法是怎么来的?
    • 先从自己身上找 >> __proto__身上找 >> prototype身上找 >> 再往上一级找… >> Object.prototype.__proto__ 最终找到了Object上

语法参考:

1
2
3
4
5
6
7
8
// 1.创建构造函数
function CreateList(arg1, ...) { //如 赋值操作 }
// 2.创建原型方法
CreateList.prototype.render = function () { //如 渲染页面操作 }
// 3.new 对象
let obj = new CreateList(xx, yy)
// 4.调用方法
obj.render()

案例:面向对象应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>

<body>
<div class="box1">
<h1></h1>
<ul></ul>
</div>
<div class="box2">
<h1></h1>
<ul></ul>
</div>
<script>
let data1 = {
title: "体育",
list: ["体育-1", "体育-2", "体育-3"]
}
let data2 = {
title: "综艺",
list: ["综艺-1", "综艺-2", "综艺-3"]
}

function CreateList(select, data) {
this.ele = document.querySelector(select)
this.title = data.title
this.list = data.list
// this.render = function() {...}
}

// prototype 原型,共享内存;且对象能够直接访问到该方法
// 对象.__proto__ === 构造函数.prototype
CreateList.prototype.render = function () {
// 渲染页面
let h1 = this.ele.querySelector("h1")
let ul = this.ele.querySelector("ul")
// console.log(h1, ul)
h1.innerHTML = this.title
ul.innerHTML = this.list.map(item => `<li>${item}</li>`).join("")
}

// 每次 new 都会占用一份内存:内存浪费;但原型不会。
let obj1 = new CreateList(".box1", data1)

console.log(obj1.__proto__) // {render: f}
console.log(CreateList.prototype) // {render: f}
console.log(obj1.__proto__ === CreateList.prototype) // true

obj1.render()
let obj2 = new CreateList(".box2", data2)
obj2.render()

// 扩展:obj1.toString()
// 原型链概念:自己身上找 >> __proto__身上找 >> prototype身上找 >> 上一级找 >> Object.prototype.__proto__ 最终找到了Object上
</script>
</body>

</html>

效果:

image-20251211163533035

原型的方法是否会被覆盖的验证:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<script>
function CreateObj(name) {
this.name = name
}
CreateObj.prototype.getName = function() {
console.log("1111", this.name)
}
var obj1 = new CreateObj("jerry")
// 此getName是原型上的方法
obj1.getName() // 1111 jerry
obj1.getName = function() {
console.log("2222")
}
// 此getName是obj1身上的方法,调用时先查找自身,所以调用的是自身的 getName
obj1.getName() // 2222

var obj2 = new CreateObj("tom")
obj2.getName()
</script>

案例:选项卡-面向对象+模块化

./Tabs.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function Tabs(select, type) {
let container = document.querySelector(select)
this.oHeaderLis = container.querySelectorAll(".header li")
this.oBoxLis = container.querySelectorAll(".box li")
// console.log(this.oHeaderLis, this.oBoxLis)
this.type = type
this.change()
}

Tabs.prototype.change = function () {
for (let i = 0; i < this.oHeaderLis.length; i++) {
// 注意:function() 时 this 会指向当前绑事件的元素即li,是不对的
//this.oHeaderLis[i].onclick = function () {
// 此时刚好需要用箭头函数(意为当前元素没有this)则this会指向父元素对象,即 Tabs 实例化对象
//this.oHeaderLis[i].onclick = () => {
this.oHeaderLis[i].addEventListener(this.type, () => {
// console.log(this)
let index = i
for (let j = 0; j < this.oHeaderLis.length; j++) {
this.oHeaderLis[j].classList.remove("active")
this.oBoxLis[j].classList.remove("active")
}
this.oHeaderLis[index].classList.add("active")
this.oBoxLis[index].classList.add("active")
})
}
}

export default Tabs

./index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}

ul {
list-style: none;
}

.header {
display: flex;
width: 600px;
}

.header li {
flex: 1;
border: 1px solid #ccc;
height: 50px;
line-height: 50px;
text-align: center;
}

.box {
position: relative;
width: 600px;
height: 150px;
}

.box li {
position: absolute;
left: 0;
top: 0;
width: 600px;
height: 100px;
line-height: 100px;
text-align: center;
background: yellow;

display: none;
}

.box .active {
background: yellow;
display: block;
}

.header .active {
background: red;
}
</style>
</head>

<body>
<div class="container1">
<ul class="header">
<li class="active">1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<ul class="box">
<li class="active">111</li>
<li>222</li>
<li>333</li>
<li>444</li>
<li>555</li>
</ul>
</div>
<div class="container2">
<ul class="header">
<li class="active">1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<ul class="box">
<li class="active">111</li>
<li>222</li>
<li>333</li>
<li>444</li>
<li>555</li>
</ul>
</div>

<!-- 方式一:直接先引入,后使用 -->
<!-- <script src="Tabs.js"></script> -->
<!-- 方式二:模块化方式 - 推荐 -->
<script type="module">
import MyTabs from './Tabs.js'

// 鼠标点击切换
new MyTabs(".container1", "click")
// 鼠标移入切换
new MyTabs(".container2", "mouseover")
</script>
</body>

</html>

效果:

chrome-capture-2025-12-11 (1)

7.3 class

语法:

1
2
3
4
5
6
7
8
9
10
11
class CreateObj {
// 构造器函数
constructor(name) {
this.name = name
}
//原型下的方法,等价于 CreateObj.prototype.say = function() {...}
say() { console.log(this.name, "hello") }
}
let obj = new CreateObj("jerry")
console.log(obj) // {name: 'jerry'}
obj.say() // jerry hello

示例:选项卡-面向对象+模块化+class 改造

./Tabs.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Tabs {
constructor (select, type) {
let container = document.querySelector(select)
this.oHeaderLis = container.querySelectorAll(".header li")
this.oBoxLis = container.querySelectorAll(".box li")
this.type = type
this.change()
}

change() {
for (let i = 0; i < this.oHeaderLis.length; i++) {
this.oHeaderLis[i].addEventListener(this.type, () => {
let index = i
for (let j = 0; j < this.oHeaderLis.length; j++) {
this.oHeaderLis[j].classList.remove("active")
this.oBoxLis[j].classList.remove("active")
}
this.oHeaderLis[index].classList.add("active")
this.oBoxLis[index].classList.add("active")
})
}
}
}

export default Tabs

效果是一致的。

7.4 继承

  • 构造函数继承
1
2
3
4
function Student(name, age, score) {
Person.call(this, name, age)
this.score = score
}
  • 原型继承
1
Student.prototype = new Person()
  • 组合继承(一般都是组合继承
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
function Person(name, age) {
this.name = name
this.age = age
}
Person.prototype.say = function() {
console.log(this.name, "hello")
}
function Student(name, age, grade) {
// 构造函数继承:call 和 apply 效果一样
Person.call(this, name, age)
//Person.apply(this, [name, age])
this.grade = grade
}
Student.prototype = new Person()
// 增加方法
Student.prototype.printGrade = function() {
console.log(this.name, this.grade)
}
// 覆盖相同say方法:不影响Person的say方法
Student.prototype.say = function() {
console.log(this.name, "你好!!!")
}
// 增强新的say方法:起一个新的名字,并内部调用原say方法
Student.prototype.say2 = function() {
// 方式一
this.say()
// 方式二
//Person.prototype.say.call(this)
console.log(this.name, "你好222!!!")
}

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<script>
function Person(name, age) {
this.name = name
this.age = age
}
Person.prototype.say = function() {
console.log(this.name, "hello")
}

function Student(name, age, grade) {
// 构造函数继承:call 和 apply 效果一样
// Person.call(this, name, age)
Person.apply(this, [name, age])
this.grade = grade
}

// 原型继承
Student.prototype = new Person()
Student.prototype.printGrade = function() {
console.log(this.name, this.grade)
}
// 覆盖原say方法
Student.prototype.say = function() {
console.log(this.name, "你好!!!")
}
// 增强新的say方法:起一个新的名字,并内部调用原say方法
Student.prototype.say2 = function() {
// 方式一
this.say()
// 方式二
//Person.prototype.say.call(this)
console.log(this.name, "你好222!!!")
}

let st = new Student("jerry", 18, 100)
console.log(st) // {name: 'jerry', age: 18, grade: 100}
st.say() // jerry hello
st.printGrade() // jerry 100
st.say2()

let st2 = {
grade: 150
}
Person.call(st2, "tom", 20)
console.log(st2) // {grade: 150, name: 'tom', age: 20}
</script>

案例:继承应用

添加一个图片的属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>

<body>
<div class="box1">
<h1></h1>
<ul></ul>
</div>
<div class="box2">
<h1></h1>
<img src="" alt="" style="width: 100px;">
<ul></ul>
</div>
<script>
let data1 = {
title: "体育",
list: ["体育-1", "体育-2", "体育-3"]
}
let data2 = {
title: "综艺",
url: "https://static.maizuo.com/pc/v5/usr/movie/53443bf08ac8f08d23e3fe35959a3240.jpg?x-oss-process=image/quality,Q_70",
list: ["综艺-1", "综艺-2", "综艺-3"]
}

//添加默认值防止报错:data={}
function CreateList(select, data={}) {
this.ele = document.querySelector(select)
this.title = data.title
this.list = data.list
}

CreateList.prototype.render = function () {
let h1 = this.ele.querySelector("h1")
let ul = this.ele.querySelector("ul")
h1.innerHTML = this.title
ul.innerHTML = this.list.map(item => `<li>${item}</li>`).join("")
}

let obj1 = new CreateList(".box1", data1)
obj1.render()

function CreateImgList(select, data) {
CreateList.call(this, select, data)
this.imgUrl = data.url //新增的
}
CreateImgList.prototype = new CreateList()
CreateImgList.prototype.newRender = function() {
//渲染页面
this.render()
let img = this.ele.querySelector("img")
img.src = this.imgUrl
}

let obj2 = new CreateImgList(".box2", data2)
obj2.newRender()

</script>
</body>

</html>

效果:

image-20251211181942700

7.5 ES6继承

  • class 子类 extends 父类 {} ES6继承语法(类似java写法,好记)
  • super(arg...) 构造函数; super.方法() 普通函数
1
2
3
4
5
6
7
8
9
10
class 子类 extends 父类 {
constructor(arg1, arg2, arg3, ...) {
super(arg1, arg2) // 继承父类的属性
this.arg3 = arg3
}
方法() { //覆盖父类方法,子类使用【类似java的方法重写】
super.方法() // 调用父类的方法
//自己方法执行的逻辑
}
}

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<script>
class Person {
constructor(name, age) {
this.name = name
this.age = age
}
say() {
console.log(this.name, "hello")
}
}
// extends 原型继承:把父类的方法继承过来了
class Student extends Person{
constructor(name, age, grade) {
// 继承父类的属性
super(name, age)
this.grade = grade
}
//覆盖父类方法,子类使用【类似java的方法重写】
say() {
super.say() // 调用父类的方法
console.log(this.name, "你好")
}
}

let st = new Student("jerry", 18, 100)
console.log(st)
st.say()
</script>

案例:继承应用-ES6改造

核心:extends 继承、super父类构造函数和调用父类方法、子类重名方法的重写增强、render渲染放在构造函数中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>

<body>
<div class="box1">
<h1></h1>
<ul></ul>
</div>
<div class="box2">
<h1></h1>
<img src="" alt="" style="width: 100px;">
<ul></ul>
</div>
<script>
let data1 = {
title: "体育",
list: ["体育-1", "体育-2", "体育-3"]
}
let data2 = {
title: "综艺",
url: "https://static.maizuo.com/pc/v5/usr/movie/53443bf08ac8f08d23e3fe35959a3240.jpg?x-oss-process=image/quality,Q_70",
list: ["综艺-1", "综艺-2", "综艺-3"]
}

class CreateList {
constructor(select, data = {}) {
this.ele = document.querySelector(select)
this.title = data.title
this.list = data.list
this.render()
}
render() {
let h1 = this.ele.querySelector("h1")
let ul = this.ele.querySelector("ul")
h1.innerHTML = this.title
ul.innerHTML = this.list.map(item => `<li>${item}</li>`).join("")
}
}

new CreateList(".box1", data1)

class CreateImgList extends CreateList {
constructor(select, data) {
super(select, data)
this.imgUrl = data.url //新增的
this.render()
}
render() {
super.render()
let img = this.ele.querySelector("img")
img.src = this.imgUrl
}
}
new CreateImgList(".box2", data2)
</script>
</body>

</html>

效果是一样的。

1
2
3
4
5
6
7
8
07-Ajax异步请求&跨域&闭包
08-jQuery的使用

02_CSS
14-Sass的使用

07_Bootstrap
08-再谈Boorstrap

06-ES6特点
https://janycode.github.io/2018/05/07/04_大前端/03_JavaScript/06-ES6特点/
作者
Jerry(姜源)
发布于
2018年5月7日
许可协议