面向对象特性:封装性 继承性 多态性
面向对象的思维特点
- 抽取抽象对象共用的属性和行为封装成一个类(模板)
- 对类进行实例化,获取类的对象
万物皆对象,对象是一个具体事物,
对象有属性和方法
类抽象了对象的公共部分,泛指一大类
对象特指某一个,通过类实例化一个具体的对象
es6创建类
constructor()方法是类的构造函数,用于传递参数,返回实例对象
// 1.创建类 class 明星类
class Star {
constructor(uname, age) {
this.uname = uname
this.age = age
}
}
// 2. 利用类创建对象 new
var ldh = new Star('刘德华', 30)
var zxy = new Star('张学友')
console.log(ldh)
console.log(zxy.uname)
//Star { uname: '刘德华', age: 30 }
//张学友
- 通过class关键字创建类,类名首字母大写
- 类里的constructor函数,可以接收传递过来的参数,同时返回实例对象
- constructor函数只要new生成实例时,就会自动调用这个函数,如果不写这这个函数,类也会自动生成这个函数
- 生成实例 new不能省
- 创建类 类名后不加小括号,生成实例 类名后加小括号,构造函数不需要加function
类中添加共有方法
多个函数方法之间不需要添加逗号分隔
// 1.创建类 class 明星类
class Star {
constructor(uname, age) {
this.uname = uname
this.age = age
}
sing(song) {
console.log(this.uname+'sing'+song)
}
}
// 2. 利用类创建对象 new
var ldh = new Star('刘德华', 30)
var zxy = new Star('张学友')
console.log(ldh)
console.log(zxy.uname)
ldh.sing('冰雨')
类继承extends和super关键字
class Father {
constructor(x, y) {
this.x = x
this.y = y
}
sum() {
console.log(this.x + this.y)
}
money() {
console.log(100)
}
}
class Son extends Father{
constructor(x, y) {
super(x, y); //调用了父类中的构造函数
}
}
var son = new Son(1, 3)
var son2 = new Son(11, 3)
son.money() //100
son.sum() //4
son2.sum()//14
super
class Father {
say() {
return '我是爸爸'
}
}
class Son extends Father {
say() {
// console.log('我是二字')
console.log(super.say()+'的儿子')
// super.say() 调用父类中的普通函数
}
}
var son = new Son()
son.say() // 我是爸爸的儿子
// 继承中的属性或方法查找原则:就近原则
子类继承父类的方法同时扩展自己的方法
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之前调用
super(x, y)
this. x = x
this.y = y
}
subtract() {
console.log(this.x - this.y)
}
}
var son = new Son(10, 5)
son.sum() // 15
son.subtract() // 5
使用类的注意点:
在es6中类没有变量提升,所以必须先定义类,才能通过类实例化对象
类里面共有的属性和方法一定要加this使用
类里面的this指向
constructor里面的this指向的是 创建的实例对象
方法里面的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>Document</title>
</head>
<body>
<button>点击</button>
<script>
var that;
class Star {
constructor(uname, age) {
// constructor里面的this指向的是 创建的实例对象
that = this
this.uname = uname
this.age = age
this.btn = document.querySelector('button')
// 这里的sing是btn调用的 指向btn btn.uname为undefined 可以把this改为that
this.btn.onclick = this.sing
}
sing() {
// 解决方法 把这里的this改为that
// console.log(this.uname)
console.log(that.uname)
}
}
var ldh = new Star('刘德华')
console.log(that === ldh)
</script>
</body>
</html>
面向对象tab栏
功能需求:
- 点击tab栏,可以切换效果
- 点击+号,可以添加tab项和内容项
- 点击x号,可以删除当前的tab项和内容项
- 双击tab项文字或者内容项文字,可以修改里面的内容
抽取对象 tab对象
该对象具有切换功能
该对象具有添加功能
改对象具有删除功能
该对象具有修改功能
添加功能:点击+可以实现添加新的选项卡和内容
5. 创建新的选项卡li 和新的内容section
6. 把创建的两个元素追加到对应的父元素中
以前的做法:动态创建元素createElement
,但是元素里面内容较多,需要innerHTML赋值 ,在appendChild追加到父元素里面
现在高级做法:利用insertAdjacentHTML()
可以直接把字符串格式元素添加到父元素中
删除功能;
点击x可以删除当前的li选项卡和当前的section
x是没有索引号的,但是它的父亲li有索引号,这个索引号正是我们想要的索引号
所以核心思路是: 点击x号可以删除这个索引号对应的li和section
编辑功能:
双击选项卡li或者section里面的文字,可以实现修改功能
双击事件:ondblclick
如果双击文字,会默认选定文字,此时需要双击禁止选中文字
window.getSelection?window.getSelection().removeAllRanges(): document.selectionempty()
核心思路:双击文字的时候,在里面生成一个文本框,当失去焦点或者按下回车 然后把文本框的值给原先的元素即可
代码
构造函数和原型
在es6之前,对象不是基于类创建的,而是构造函数这种特殊函数来定义对象和它们的特征
创建对象三种方式:
- new Objext()创建对象
- 对象字面量
- 构造函数
new在执行时会做四件事 - 在内存中创建一个新的对象
- 让this指向这个新的对象
- 执行构造函数里面的代码,给这个新对象添加属性和方法
- 返回这个新对象(所以构造函数里面不需要return)
实例成员和静态成员
// 构造函数中的属性和方法称为成员 成员可以添加
function Star(uname, age){
this.uname = uname
this.age = age
this.sing = function(){
console.log('唱歌')
}
}
var ldh = new Star('刘德华',18)
var zxy = new Star('张学友',10)
// 实例成员就是构造函数内部通过this添加的成员 uname age sing就是实例成员
// 实例成员只能通过实例化的对象来访问
console.log(ldh.uname)
ldh.sing()
console.log(Star.uname) // 不可以通过构造函数来访问实例成员
// 静态成员 在构造函数本身上添加的成员
Star.sex = '男' // 此时sex是静态成员 只能通过构造函数
console.log(ldh.sing() === zxy.sing()) // false
构造函数原型对象prototype
构造函数方法很好用,但是存在浪费内存的问题
我们希望所有的对象使用同一个函数,这样就比较节省内存,但是应该如何做
构造函数通过原型分配的函数是所有对象所共享的
每一个构造函数都有一个prototype对象
我们可以把那些不变的方法,直接定义在prototyoe对象上,这样所有的对象的实例就可以共享这些方法
// 构造函数中的属性和方法称为成员 成员可以添加
function Star(uname, age){
this.uname = uname
this.age = age
// this.sing = function(){
// console.log('唱歌')
// }
}
Star.prototype.sing = function() {
console.log('我们唱歌')
}
var ldh = new Star('刘德华',18)
var zxy = new Star('张学友', 30)
ldh.sing()
zxy.sing()
console.log(ldh.sing() === zxy.sing()) // true
原型是什么:
一个对象,我们也称为prototype为原型对象
原型的作用是什么:
共享方法
一般情况下,我们的公共属性定义到构造函数里面,公共的方法我们放到原型对象上
对象原型__proto__
对象身上系统自动添加一个__proto__指向我们的构造函数的原型对象
console.log(ldh.__proto__ === Star.prototype) // true
方法的查找规则:
说先看ldh实例对象身上是否有sing方法,如果有就执行这个对象上的sing
如果没有,因为__proto__的存在,就去构造函数原型对象prototype身上去查找sing这个方法