1.Class是什么
-
认识class
人类:类
具体的人:实例、对象
类可以看做是对象的模板,用一个类可以创建许多不同的对象 -
Class基本用法
类名一般大写
class Person {}
class Person {
//实例化时执行的构造方法,所以必须有构造方法,但是可以不写出来
constructor(name, age) {
console.log('初始化构造方法');
this.name = name;
this.age = age;
// 一般在构造方法中定义属性,方法不在构造方法中定义 (会开辟多个内存空间)
// this.speak = () => {}
}
// 各实例共享方法
speak() {
console.log('speck!');
}
}
const zs = new Person('zhangsan', 20);
const ls = new Person('lisi', 20);
console.log(zs.name); //zhangsan
console.log(zs.age); //20
zs.speak(); //speck!
console.log(ls.name); //lisi
console.log(ls.age); //20
ls.speak(); //speck!
console.log(zs.speak === ls.speak); //true
- class 和 构造函数
class Person {
constructor(name, age) {
console.log('初始化构造方法');
this.name = name;
this.age = age;
// this.speak = () => {}
}
speak() {
console.log('speck!');
}
}
// 构造函数
function Person(name, age) {
this.name = name;
this.age = age;
// this.speak = () => {}
}
Person.prototype.speak = function() {}
2.Class的两种形式
- 声明形式
class Person {
constructor() {}
speak() {}
}
- 表达式形式
构造函数
function Person() {}
Class类
const Person = class {
constructor() {
console.log('constructor');
}
speak() {}
}
new Person(); //constructor
// 立即执行函数
(function() {
console.log('立即执行函数!');
})()
// 立即执行类
new(class {
constructor() {
console.log('立即执行类!'); //立即执行类!
}
})()
3.实例属性、静态方法、静态属性
- 实例属性
方法就是值为函数的特殊属性
class Person {
age = 0;
sex = 'nan';
getSex = function() {
return this.sex;
}
constructor(name, sex) {
this.name = name;
this.sex = sex;
}
speak() {}
}
const p = new Person('zhangsan', 'nv');
console.log(p.name); //zhangsan
console.log(p.sex); //nv
console.log(p.age); //0
console.log(p.getSex());
- 静态方法
类的方法
class Person {
constructor(name, sex) {
this.name = name;
this.sex = sex;
};
speak() {
console.log('speak!!');
};
// 静态方法
static speak() {
console.log('静态方法!');
}
}
const p = new Person('zhangsan', 'nan');
p.speak(); //speak!!
//调用静态方法
Person.speak(); //静态方法!
- 静态属性
class Person {
constructor(name) {
this.name = name;
}
static getVersion() {
return '1.0';
}
}
const p = new Person('zhangsan');
console.log(p.name);
console.log(Person.getVersion());
4.私有的方法和属性
- 为什么需要私有属性和方法
一般情况下,类的属性和方法都是公开的
公有的属性和方法可以被外界修改,造成意想不到的后果
class Person {
constructor(name) {
this.name = name;
}
speak() {
console.log('speak!!');
}
getName = function() {
return this.name;
}
}
const p = new Person('张三');
console.log(p.name);
p.speak();
//...
p.name = '李四';
console.log(p.name);
console.log(p.getName());
- 模拟私有属性
2.1 _开头表示私有
class Person {
constructor(name) {
this._name = name;
}
speak() {
console.log('speak');
}
getName() {
return this._name;
}
}
const p = new Person('zhangsan');
console.log(p.name); //undefined
p.name = 'liso';
console.log(p.getName()); //zhangsan
2.2 将私有属性和方法移出类
(function() {
let name = '';
class Person {
constructor(username) {
// this.name = name;
name = username;
}
speak() {
console.log('speak');
}
getName() {
return name;
}
}
window.Person = Person;
})();
(function() {
const p = new Person('zhangsan');
console.log(p.name); //undefined
console.log(p.getName()); //zhangsan
})()
5.extends
- 子类继承父类
class Person {
constructor(name) {
this.name = name;
this.say = function() {
console.log('say!');
}
}
speak() {
console.log('speck');
}
static speak() {
console.log('static speck');
}
}
Person.version = '1.0';
//继承
// class A extends Person {
// constructor(name) {
// super(name);
// }
// }
// const zs = new A('zhangsan');
// console.log(zs.name); //zhangsan
// zs.say(); //say!
// zs.speak(); //speck
// A.speak(); //static speck
// console.log(A.version); //1.0
// 重写
class A extends Person {
constructor(name, sex) {
super(name);
//this的操作不能放在super前面
this.sex = sex;
}
hi() {
console.log('hi!');
}
// 同名覆盖
speak() {
console.log('重写speak方法');
}
static speak() {
console.log('重写 static speck 方法');
}
}
A.version = '2.0';
const zs = new A('zhangsan', '男');
console.log(zs.name); //zhangsan
console.log(zs.sex); //男
zs.hi(); //hi!
zs.say(); //say!
zs.speak(); //speck
A.speak(); //static speck
console.log(A.version); //1.0
6.super
- 作为函数调用
代表父类的构造的方法,只能用在之类的构造方法中,用在其他地方就会报错
super虽然代表了父类的构造方法,但是内部的this指向子类的实例
class Person {
constructor(name) {
this.name = name;
console.log(this);
}
}
class A extends Person {
constructor(name, sex) {
super(name);
this.sex = sex;
}
}
new Person();
-
作为对象使用
2.1 在构造方法中或一般方法中使用super 代表父类的原型Person.prototype
通过super调用父类方法时,方法内部的this指向当前的子类实例
class Person {
constructor(name) {
this.name = name;
console.log(this);
}
speak() {
console.log('speak!'); //speak!
}
}
class A extends Person {
constructor(name, sex) {
super(name);
this.sex = sex; //undefined
console.log(super.name); //A {name: undefined}
super.speak();
}
}
// new Person();
new A();
- 注意事项
使用super的时候, 必须显示指定的作为函数还是作为对象使用, 否则会标错
class Person {
constructor(name) {
this.name = name;
console.log(this);
}
speak() {
console.log('speak!'); //speak!
}
}
class A extends Person {
constructor(name, sex) {
super(name, sex);
}
}
7.Classs的应用
/* css reset */
* {
padding: 0;
margin: 0;
}
a {
text-decoration: none;
outline: none;
}
img {
vertical-align: top;
}
/* layout */
.slider-layout {
width: 80%;
height: 420px;
margin: 0 auto;
}
/* slider */
.slider,
.slider-content,
.slider-item,
.slider-img {
width: 100%;
height: 100%;
}
.slider {
overflow: hidden;
}
.slider-item {
float: left;
}
.slider-animation {
transition-property: transform;
transition-duration: 0ms;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Class 的应用</title>
<link rel="stylesheet" href="./css/slider.css" />
</head>
<body>
<div class="slider-layout">
<div class="slider">
<div class="slider-content">
<div class="slider-item">
<a href="javascript:;"><img src="./imgs/1.jpg" alt="1" class="slider-img" /></a>
</div>
<div class="slider-item">
<a href="javascript:;"><img src="./imgs/2.jpg" alt="1" class="slider-img" /></a>
</div>
<div class="slider-item">
<a href="javascript:;"><img src="./imgs/3.jpg" alt="1" class="slider-img" /></a>
</div>
<div class="slider-item">
<a href="javascript:;"><img src="./imgs/4.jpg" alt="1" class="slider-img" /></a>
</div>
</div>
</div>
</div>
<script src="./js/base.js"></script>
<script>
// console.log(BaseSlider);
class Slider extends BaseSlider {
constructor(el, options) {
super(el, options);
this._bindEvent();
}
_bindEvent() {
document.addEventListener('keyup', ev => {
// console.log(ev.keyCode);
if (ev.keyCode === 37) {
// ←
this.prev();
} else if (ev.keyCode === 39) {
// →
this.next();
}
});
}
}
new Slider(document.querySelector('.slider'), {
initialIndex: 1,
animation: true,
speed: 1000
});
</script>
</body>
</html>