Class
# Class
JS中并不存在类,class只是语法糖,本质还是函数。
class Person {}
Person instanceof Function // true
// 即Person. __proto__===Function. prototype
1
2
3
2
3
[TOC]
# 一、基本语法
let dragBox = new Drag(box);
class Drag {
// 构造函数
constructor(el){
this.el=el;
}
}
console.log(dragBox)
Drag
////el:div#box
////_proto_: Object
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
// ECMAScript 2015 中引入的 JavaScript 类实质上是 JavaScript 现有的基于原型的继承的语法糖。
// 类语法不会为JavaScript引入新的面向对象的继承模型。
// 类声明
// 函数声明和类声明之间的一个重要区别是函数声明会提升,类声明不会。
// 你首先需要声明你的类,然后访问它。
class Drag {
// 构造函数
constructor(el){
this.el = el;
// 鼠标摁下时的元素的位置
this.startOffset = {};
// 鼠标摁下时鼠标的坐标
this.startPoint = {};
let move = (e)=>{
this.move(e);
};
let end = (e)=>{
document.removeEventListener("mousemove",move);
document.removeEventListener("mouseup",end);
};
el.addEventListener("mousedown",(e)=>{
// 由于箭头函数不绑定this
// 它会捕获其所在(即定义的位置)上下文的this值, 作为自己的this值
this.start(e);
// 下面这两个语句放在mousedown里,才能确保只有鼠标按下后才会执行
// 因为执行结束后都要被清除,所以不能直接用匿名函数
// 这里用document,而不用el,就是为了避免鼠标滑动过快,移出拖拽对象
document.addEventListener("mousemove",move);
document.addEventListener("mouseup",end);
});
}
// 摁下时的处理函数
start(e){
// 解构赋值
// 等价于 let el = this.el
let {el} = this;
this.startOffset = {
x: el.offsetLeft,
y: el.offsetTop
};
this.startPoint = {
x: e.clientX,
y:e.clientY
};
}
//移动时的处理函数
move(e){
let {el,startOffset,startPoint} = this;
let nowPoint = {
x: e.clientX,
y: e.clientY
};
let dis = {
x: nowPoint.x - startPoint.x,
y: nowPoint.y - startPoint.y
}
el.style.left = dis.x + startOffset.x + "px";
el.style.top = dis.y + startOffset.y + "px";
}
}
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
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
# 二、静态方法
类相当于实例的原型, 所有在类中定义的方法, 都会被实例继承。 如果在一个方法前, 加上static关键字, 就表示该方法不会被实例继承, 而是直接通过类来调用, 这就称为“ 静态方法”。
class Foo {
static classMethod() {
return 'hello';
}
}
Foo.classMethod() // 'hello'
var foo = new Foo();
foo.classMethod() // TypeError: foo.classMethod is not a function
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
上面代码中, Foo类的classMethod方法前有static关键字, 表明该方法是一个静态方法, 可以直接在Foo类上调用( Foo.classMethod()), 而不是在Foo类的实例上调用。 如果在实例上调用静态方法, 会抛出一个错误, 表示不存在该方法。
- 父类的静态方法, 可以被子类继承。
class Bar extends Foo {}
Bar.classMethod(); // 'hello'
1
2
2
上面代码中, 父类Foo有一个静态方法, 子类Bar可以调用这个方法。
- 静态方法也是可以从super对象上调用的。
class Bar extends Foo {
static classMethod() {
return super.classMethod() + ', too';
}
}
Bar.classMethod(); // "Hello, too"
1
2
3
4
5
6
2
3
4
5
6
# 请实现一个 Event 类,继承自此类的对象都会拥有四个方法 on, off, once 和 trigger。
//event.js
class Event {
constructor(){
this.handlers = {}; //记录所有的事件及处理函数
/*handles存放的类似下面的事件类型
{
click:[fn1,fn2],
mouseover: [fn3,fn4]
}
*/
}
/**
* on 添加事件监听
* @param type 事件类型
* @param handler 事件处理函数
*/
on(type,handler,once=false){
// 如果事件类型不存在的话,就给它加进去
if(!this.handlers[type]){
this.handlers[type] = [];
}
// includes()避免事件重复添加
if(!this.handlers[type].includes(handler)){
this.handlers[type].push(handler);
handler.once = once;
}
}
/**
* off 取消事件监听
* @param 用来记录所需要的参数
* @param type 要取消的事件类型
* @param handler 要取消的事件函数,如果不传则清除该类型所有函数
*/
off(type,handler){
if(this.handlers[type]){
// 如果不存在,则作清空处理
if(handler === undefined){
this.handlers[type] = [];
} else {
// filter创建一个新数组,不改变原来的数组,返回符合条件的数组
this.handlers[type] = this.handlers[type].filter(f => f!=handler);
}
}
}
/**
* trigger 执行函数
* @param type 要执行哪个类型的函数
* @param eventData 事件对象
* @param point this执行
*/
trigger(type,eventData={},point=this){
if(this.handlers[type]){
this.handlers[type].forEach(f => {
if(f.once){
this.off(type,f);
}
// call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。
f.call(point,eventData);
});
}
}
/**
* once 该函数只执行一次
* @param type 事件类型
* @param handler 事件处理函数
*/
once(type,handler){
this.on(type,handler,true);
}
}
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
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