JavaScript 面向对象
1. 面向对象介绍
1.1 面向过程
POP(Process-oriented programming)

1.2 面向对象
OOP (Object Oriented Programming)


1.3 对比

2. ES6 中的类和对象
2.1 前言

2.2 对象

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 Restudy() {
var ldh = { name: '刘德华', age: 18 } console.log(ldh);
var zxy = new Object() zxy.name = '张学友' zxy.age = 19 console.log(zxy);
function Star(name, age) { this.name = name; this.age = age; } var lm = new Star('黎明', 20) console.log(lm); }
|
2.3 类class
2.31 解读

2.32 创建类

2.33 类 constructor 构造函数

2.34 类创建添加属性和方法

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
class star { constructor(uname, age) { this.uname = uname; this.age = age; } sing(song) { console.log(this.uname + '唱' + song); } }
var cl = new star('成龙', 20) cl.sing('北京欢迎你') var zhj = new star('周华健', 21) zhj.sing('123') console.log(cl); console.log(zhj);
|
注意:
- 通过class 关键字创建类, 类名我们还是习惯性定义首字母大写
- 类里面有个constructor 函数,可以接受传递过来的参数,同时返回实例对象
- constructor 函数 只要 new 生成实例时,就会自动调用这个函数, 如果我们不写这个函数,类也会自动生成这个函数
- 多个函数方法之间不需要添加逗号分隔
- 生成实例 new 不能省略
- 语法规范, 创建类 类名后面不要加小括号,生成实例 类名后面加小括号, 构造函数不需要加function
2.35 类的继承extend


2.36 类的访问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 29 30 31 32
|
class Dadd { constructor(x, y) { this.x = x this.y = y } methodd() { console.log('父类里的方法:' + (this.x + this.y)); } }
class Sonn extends Dadd { constructor(x, y) { super(x, y)
this.x = x this.y = y } }
var child = new Sonn(1, 2); var child2 = new Sonn(1, 20); child.methodd(); child2.methodd();
|

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
|
class Father { sing() { return '我是父类里的‘唱’' } dance() { return '我是父类里的‘跳’' } rap() { return '我是父类里的‘rap’' } }
class Son extends Father { sing() { console.log(super.sing()); } dance() { console.log('我是子类里的‘跳’'); } rap() { console.log('我是子类里的‘rap’'); } }
var ikun = new Son() ikun.sing()
|
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
|
class Father { constructor(x,y){ this.x = x; this.y = y; } sum(){ console.log('父类里的sum():'+(this.x+this.y)); } }
class Son extends Father { constructor(x,y){ super(x, y)
this.x=x; this.y=y; } subtract(){ console.log('子类里的subtract():'+(this.x-this.y)); } }
var son=new Son(5,1) son.sum() son.subtract()
|
2.36 使用类注意事项
-
继承中,如果实例化子类输出一个方法,先看子类有没有这个方法,如果有就先执行子类的
-
继承中,如果子类里面没有,就去查找父类有没有这个方法,如果有,就执行父类的这个方法(就近原则)
-
如果子类想要继承父类的方法,同时在自己内部扩展自己的方法,利用super 调用父类的构造函数,super 必须在子类this之前调用
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
| 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(x, y); this.x = x; this.y = y;
} subtract() { console.log(this.x - this.y); } } var son = new Son(5, 3); son.subtract(); son.sum();
|
以上代码运行结果为:

-
时刻注意this的指向问题,类里面的共有的属性和方法一定要加this使用
constructor中的this指向的是new出来的实例对象
自定义的方法,一般也指向的new出来的实例对象
绑定事件之后this指向的就是触发事件的事件源
-
在 ES6 中类没有变量提升,所以必须先定义类,才能通过类实例化对象


3. 面向对象案例
3.1 案例要求
- 点击 tab栏,可以切换效果.
- 点击 + 号, 可以添加 tab 项和内容项.
- 点击 x 号, 可以删除当前的tab项和内容项.
- 双击tab项文字或者内容项文字可以修改里面的文字内容
3.2 实现页面

3.3 案例分析
3.31 Tab对象

3.32 切换功能
参考Dom自定义属性操作和排他思想
3.33 添加功能

3.34 删除功能

3.35 编辑功能

3.4 代码结构
3.41 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
| <!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"> <script src="index.js"></script> </head>
<body> <main> <h4>Js面对对象 动态添加标签页</h4> <div class="tabbox"> <nav> <ul> <li class="liactive"><span >测试1</span><span class="close">X</span></li> <li><span>测试2</span><span class="close">X</span></li> <li><span>测试3</span><span class="close">X</span></li> </ul> <div class="add"> <span>+</span> </div> </nav> <div class="tab_content"> <section class="conactive">测试1</section> <section>测试2</section> <section>测试3</section> </div> </div> </main> </body>
</html>
|
3.42 CSS
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 109 110 111 112
| // out:index.css * { margin: 0; padding: 0; }
@font-face { font-family: 'solar'; src: url('./YeZiGongChangChuanQiuShaXingKai-2.ttf'); }
main { width: 800px; margin: 150px auto;
h4 { text-align: center; padding: 20px 0; }
.tabbox { border: 1px solid rgb(209, 79, 28);
nav { width: 100%; height: 50px; border-bottom: 1px solid #ccc;
ul { list-style: none;
li { float: left; text-align: center; line-height: 50px; width: 100px; border-right: 1px solid #ccc; border-bottom: 1px solid #ccc; box-sizing: border-box; position: relative; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
span:first-child { padding: 0 10px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
input { width: 80%; height: 25px; } }
.close { position: absolute; right: 0; background-color: black; color: white; width: 15px; height: 15px; line-height: 15px; font-size: 10px; cursor: pointer; border-bottom-left-radius: 100%; } }
li.liactive { box-sizing: border-box; border-bottom: 1px solid rgb(255, 255, 255) } }
.add { float: right; width: 20px; height: 20px; text-align: center; line-height: 20px; margin: 15px; border: 1px solid #ccc; cursor: pointer; } }
.tab_content { width: 100%; height: 400px;
section { display: none; margin: 10px; height: 95%; font-family: 'solar';
input { text-align: start; width: 100%; height: 100%; } }
section.conactive { display: block; } } } }
|
3.42 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 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 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
window.addEventListener('load', function (e) { var that; class Tab { constructor(tabbox) { this.tabbox = document.querySelector(tabbox); this.add = this.tabbox.querySelector('.add').children[0]; this.ul = this.tabbox.querySelector('ul'); this.content = this.tabbox.querySelector('.tab_content'); that = this this.init() }
init() { this.updataNode() 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.deleteTab this.spans[i].ondblclick = this.editTab this.content.children[i].ondblclick = this.editTab } this.add.onclick = this.addTab }
updataNode() { this.lis = this.tabbox.querySelectorAll('li'); this.sections = this.tabbox.querySelectorAll('section'); this.remove = this.tabbox.querySelectorAll('.close'); this.spans = this.tabbox.querySelectorAll('nav>ul>li span:first-child'); }
clearClass() { for (var i = 0; i < that.lis.length; i++) { that.lis[i].className = '' that.sections[i].className = '' } }
toggleTab() { that.clearClass() this.className = 'liactive' that.sections[this.index].className = 'conactive' }
addTab() { that.clearClass() var random = Math.random() * 100 var newli = '<li class="liactive"><span >测试' + parseInt(random) + '</span><span class="close">X</span></li>' var newSection = '<section class="conactive">测试' + parseInt(random) + '</section>'
that.ul.insertAdjacentHTML('beforeend', newli) that.content.insertAdjacentHTML('beforeend', newSection)
that.init() }
deleteTab(e) { if (that.lis.length <= 1) return e.stopPropagation(); var index = this.parentNode.index that.lis[index].remove() that.content.children[index].remove() that.init()
if (document.querySelector('.liactive')) return
index == 0 && that.lis[index++].click()
index-- that.lis[index] && that.lis[index].click() }
editTab() { var str = this.innerHTML; window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty(); this.innerHTML = '<input type="text" />' var input = this.children[0] input.value = str input.select() input.onblur = function () { this.parentNode.innerHTML = this.value; } input.onkeyup = function (e) { if (e.keyCode === 13) { this.blur(); } } } } new Tab('.tabbox') });
|