1、ES6面向对象:
- class(类) 构造函数
- 对象 实例对象
- ES5面向对象是模拟面向对象。
抽象: 具体:
人类 张三
动物类 熊猫
鸟类 黄鹂
植物类 仙人球
哺乳动物 人
2、继承
- 类使用extends关键字实现类的继承
class child extends father{
}
- 子类也必须具有一个constructor的构造函数,如果没有,那么继承父类的,如果有那么使用自己的,子类的构造函数里面必须调用父类的构造函数,也就是必须要运行super()函数。
- 其他的地方或者方法中想要调用父类的其他方法,则使用 super.函数名 的方法来实现,super表示父类。
- bind(), call ,apply 都可以偏正一个函数内部的this。
eg:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script>
function A(name,age){
this.name = name;
this.age = 19;
}
A.prototype.showName = function(){
return `我的名字是:${this.name}`;
};
A.prototype.showAge = function(){
// 字符串模板 ${}插入变量
return `我的年龄是:${this.age}`;
};
function B(name,age,use){
A.apply(this,[name,age]);
this.use = use;
}
console.log(B.prototype.constructor);
/*ƒ B(name,age,use){
A.apply(this,[name,age]);
this.use = use;
}*/
B.prototype = new A('','');
console.log(B.prototype.constructor);
/*
ƒ A(name,age){
this.name = name;
this.age = 19;
}
*/
let b = new B('zhangsan','lisi','nouse');
console.log(b.showName());
console.log(b.showAge());
/*
我的名字是:zhangsan
我的年龄是:19
*/
</script>
</html>
3、多继承
eg:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script>
function A(name,age){
this.name = name;
this.age = 19;
}
A.prototype.showName = function(){
console.log(`我的名字是:${this.name}`);
};
A.prototype.showAge = function(){
console.log(`我的年龄是:${this.age}`);
};
function B(sex){
this.sex = sex;
}
B.prototype.showSex = function(){
console.log(`我的性别是:${this.sex}`);
};
function C(use){
this.use = use;
}
//封装多继承
C.prototype.extends = function(obj,...data){
obj.apply(this,[...data]); //对象 属性值
// 合并多个javascript对象
Object.assign(C.prototype,obj.prototype);
C.prototype.constructor = C;
};
let c = new C('nouse');
c.extends(A,'lisi','19');
c.extends(B,'felame');
console.log(c.showName());
console.log(c.showSex());
/*
未封装多继承写法
C.prototype = Object.create(A.prototype);
Object.assign(C.prototype,B.prototype);
C.prototype.constructor = C;
let c = new C('lisi','19','felame','nouse');
console.log(c.showName());
console.log(c.showSex());
*/
</script>
</html>
4、单个方法的继承
eg:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script>
function F(){
}
F.prototype.h = function(){
console.log('h');
}
F.prototype.m = function(){
console.log('m');
}
function L(){
}
L.prototype.m = function(){
F.prototype.m.call(this);
}
let l = new L();
l.m();
</script>
</body>
</html>
5、constructor: 类的构造函数,类在实例化的时候自动调用,参数自动传递。
- class的属性名可以是变量,但是这个变量需要使用[]包装起来,表示变量的解析。
- class的内在本质还是一个function。
eg:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script>
const a = Symbol();
class Person{
constructor(name,age){ //构造函数 new的时候自动调用,用于初始化,自动传参
this.name = name;
this.age = age;
}
// 不能有逗号
showName(){
console.log(`我的名字是:${this.name}`);
}
showAge(){
console.log(`我的年龄是:${this.age}`);
}
[a](){
console.log(`我是Symbol数据类型的函数名`);
}
}
let b = new Person('lisi','19');
b.showName();
b[a]();
console.log(typeof Person); //function
</script>
</html>
6、对于ES5的构造函数来说,本质上定义的是一个函数,函数和变量一样,具有提升的特性,所以可以在构造函数的申明之前进行实例化。
- class没有提升,所以在创建类对象的时候一定要保证类是先加载的。
-
constructor构造函数是class必须的,即使没有申明,那么class也会自动的添加一个空的constructor函数。
eg:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script>
let p = new P();
class P{
constructor(){
}
}
</script>
</body>
</html>
7、class解构
eg:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script>
class Person{
constructor(name){
this.name = name;
}
say(){
console.log(`我的名字是:${this.name}`);
}
}
let a = new Person('lisi');
a.say();
let {say} = a;
say.bind(a); //将this的对象变为a
</script>
</html>
8、setter与getter 封装class内部成员属性的作用。
- set 语法定义的函数,外部在调用函数名为属性的属性设置值的时候调用。
- get 语法定义的函数,外部在获取这个函数名为属性的属性的时候调用。
eg:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script>
const Person = class{
constructor(name){
this.name = name;
}
set age(value){ //设置这个值的时候自动调用
console.log('这里调用参数的设置');
let c = value;
console.log(c);
}
get age(){ //获取这个值的时候自动调用
console.log('这里调用参数的获取');
}
}
let a = new Person('lisi');
a.name = 'zhangsan'; //公有属性 可在外部修改
console.log(a.name); //zhangsan
console.log(a.age); //get
a.age = 1111;
console.log(a.age); //set 1111
</script>
</html>
9、有的时候我们需要不创建对象,直接使用类去执行某些事情,这个时候就可以使用静态方法。
- static 静态的,不需要实例化对象去调用的方法。
- 静态方法里面的this指类本身,而不是对象。
- 静态方法直接使用类名调用,不能使用对象调用。
- 静态的类: Math
eg:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script>
class M{
constructor(){
}
say(){
console.log(this); //实例对象
console.log('111');
}
static Q(){
console.log(this) //class
console.log('222');
}
}
let a = new M();
a.say(); //111
M.Q(); //222
</script>
</html>
10、var proxy = new Proxy(target, handler);
- target : 要进行代理的对象。
- handler:代理的规则。
- property:代理的属性
- 代理:帮助做一些事情。
eg:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script>
const obj = {
a: 1,
b: 'vsv',
c: 2,
d: 'vgfv'
}
const e = new Proxy(obj,{
// target 代理的对象 property 代理的属性
get: function(target,property){
if (typeof target[property] == 'munber') {
return target[property];
}
return 0;
}
});
console.log(e.d);
</script>
</html>
11、案例:拖拽
- 拖拽封装
class Drag{
constructor(id){
//获取拖拽对象
this.d = document.getElementById(id);
//初始化鼠标按下的相对位置
this.x = 0;
this.y = 0;
}
init(){
this.d.onmousedown = function(ev){
var ev = ev || event;
//位置
this.x = ev.clientX - this.d.offsetLeft;
this.y = ev.clientY - this.d.offsetTop;
//鼠标移动
document.onmousemove = this.move.bind(this);
document.onmouseup = this.up;
return false;
}.bind(this);
}
move(ev){
var ev = ev || event;
this.left = ev.clientX -this.x;
this.top = ev.clientY - this.y;
this.d.style.top = this.top + 'px';
this.d.style.left = this.left + 'px';
}
up(){
document.onmousemove = null;
document.onmouseup = null;
}
}
- 拖拽边界值
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
div{
width: 200px;
height: 200px;
position: absolute;
}
#d1{
background-color: red;
left: 0;
}
#d2{
background-color: blue;
right: 0;
}
</style>
</head>
<body>
<div id="d1">vdfv</div>
<div id="d2">cvad</div>
</body>
<script src="Drag.js"></script>
<script>
let drag1 = new Drag('d1');
drag1.init();
let LimitDrag = class LimitDrag extends Drag{
move(ev){
let left = ev.clientX - this.x;
let top = ev.clientY - this.y;
if (left < 0) {
left = 0;
}else if (left >= window.innerWidth - this.d.offsetWidth) {
left = window.innerWidth - this.d.offsetWidth;
}
if (top < 0) {
top = 0;
}else if (top >= window.innerHeight - this.d.offsetHeight) {
top = window.innerHeight - this.d.offsetHeight;
}
this.d.style.left = left + 'px';
this.d.style.top = top + 'px';
}
}
let drag2 = new LimitDrag('d2');
drag2.init();
</script>
</html>