class类
// class 关键字表明 类的生命 注意:javascript没有 class
// class 的作用 :面向对象编程的工具
// 这个语法糖,语义化更好,编程的复杂度也有降低;
// 1、构造函数
// 2、原型对象
function Factory() {
this.a = "我是factory里面的一条数据"
}
Factory.prototype.init = function () {
console.log("这是一个功能")
}
var fac = new Factory()
fac.init()
// class 包含了两个部分
// 1、构造函数
// 2、原型方法
class Factory {
// 构造函数变成了统一的名称 : constructor
constructor() {
this.a = "这是一条数据"
}
init() {
console.log("这是一个功能")
}
}
// 调用 class调用 和 构造函数+原型的调用 一样
var fac = new Factory()
fac.init()
拖拽案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#box1,
#box2 {
width: 100px;
height: 100px;
background: skyblue;
position: absolute;
left: 0;
top: 0;
}
#box2 {
background: springgreen;
left: 200px;
}
</style>
</head>
<body>
<div id="box1"></div>
<div id="box2"></div>
<script>
class Drag {
constructor(selector) {
// 选择拖拽的元素
this.ele = document.querySelector(selector)
// 调用事件
this.bindEvent()
}
bindEvent() {
let self = this
// 鼠标按下事件
self.ele.onmousedown = function (evt) {
let e = evt || window.event
// es6的解构赋值
let { offsetX: x, offsetY: y } = e
document.onmousemove = function (evt) {
let e = evt || window.event
// 鼠标的移动时坐标
// 为了让元素跟着鼠标点击的位置而不是跟着鼠标的 client 走
self.eleMove(e.clientX - x, e.clientY - y)
}
}
// 当鼠标抬起事件
document.onmouseup = function () {
// 清除鼠标移动事件
document.onmousemove = null
}
}
// 移动坐标
eleMove(x, y) {
this.ele.style.left = x + "px"
this.ele.style.top = y + "px"
}
}
var drag1 = new Drag("#box1")
var drag2 = new Drag("#box2")
</script>
</body>
</html>
继承
1、es5继承
// 继承 :
// 1. 构造函数里的方法,属性拿过来;
// 2. 原型对象里的方法拿过来;
// 继承 构造数里面功能和调用;
// 其实构造函数就是加工实例对象的工厂=> 给实例对象添加属性。
// javascript里面提供的构造函数继承方式灵感来自代工;
function Father() {
this.a = "hello world";
this.b = "你好世界";
}
// new Father();
// 1. 创建Father类的实例对象;
// 2. 给Father类创建的 实例对象 上面添加属性 a 和 属性 b;
function Son() {
// 方便查看去个别名,实际上没有用;
var son_ins = this;
// 狸猫换太子 用call指向;
Father.call(son_ins);
}
var son = new Son();
console.log(son)
// 1. 创建 Son 的实例对象;
// 2. 把Son的实例放在Father的构造函数里加工;
// 【 带有参数的继承 】;
function Father(a, b) {
this.a = a;
this.b = b;
}
function Son(son_a, son_b) {
// 方便查看去个别名,实际上没有用;
var son_ins = this;
// 狸猫换太子;
// call形式的参数传递;
// Father.call(son_ins , son_a , son_b );
// apply形式的参数传递; 因为使用了 arguments 所以可以省略形参;
// arguments => [ son_a , son_b ]
Father.apply(son_ins, arguments)
}
var son = new Son("hello world", "你好世界");
// 【 原型继承 】
// 1. for in 继承; ( 浅克隆继承 )
// 2. 原型链继承;
function Father() { };
Father.prototype.init = function () {
console.log("hello world")
}
function Son() { }
// 克隆人家地址;
for (var attr in Father.prototype) {
// 给 Son 的原型写入 Father 的地址;
Son.prototype[attr] = Father.prototype[attr];
}
var son = new Son();
// console.log(son);
son.init();
原型继承 1、原型链继承
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 上头有人;
function Father() {
}
Father.prototype.init = function () {
console.log("这是father里面的功能")
}
Father.prototype.show = function () {
console.log("这是father里面的功能")
}
function Son() { }
// 因为 father 的实例对象有指针指向 Father.prototype 那么此时可以把
// son原型里面的原型指针替换成 指向fahter原型对象的原型指针;
// 我们可以直接把Son 的原型对象替换成 Father 的实例对象;
Son.prototype = new Father();
Son.prototype.show = function () {
console.log("这是son里面的功能")
}
// 原型继承的方法,不要在构造函数里面写东西;
var son = new Son();
console.log(son)
son.init();
// 在子类原型对象上 new 父类的构造函数即可完成原型继承;
son.show();
// 因为Son的原型对象方法show距离更近,所以我们会优先访问到 Son 原型上的show方法;
// 就近原则
</script>
</body>
</html>
原型继承 2、for in 继承,浅克隆继承 (拖拽案例)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#box,
#box2 {
width: 100px;
height: 100px;
background: skyblue;
position: absolute;
left: 0;
top: 0;
}
#box2 {
background: springgreen;
left: 200px;
}
</style>
</head>
<body>
<div id="box"></div>
<div id="box2"></div>
<script>
function Drag(selector) {
// 拖拽的元素;
this.ele = document.querySelector(selector);
this.bindEvent();
}
// tip : 方法分割是没有逗号的;
Drag.prototype.bindEvent = function () {
var self = this;
self.ele.onmousedown = function (evt) {
// 拖拽开启;
// console.log("拖拽开启");
let e = evt || event;
// 获取 offsetX 和 offsetY;
let { offsetX: x, offsetY: y } = e;
document.onmousemove = function (evt) {
let e = evt || event;
// 拖拽进行中;
// console.log("拖拽进行中");
// 为了让元素跟着鼠标点击的位置走而不是跟着鼠标的client 走;
self.eleMove(e.clientX - x, e.clientY - y);
}
}
this.ele.onmouseup = function () {
// console.log("拖拽结束");
document.onmousemove = null;
}
}
Drag.prototype.eleMove = function (x, y) {
this.ele.style.left = x + "px";
this.ele.style.top = y + "px";
}
function BoundaryDrag(selector) {
var son_ins = this;
Drag.call(son_ins, selector);
}
for (var attr in Drag.prototype) {
BoundaryDrag.prototype[attr] = Drag.prototype[attr];
}
// 使用的时候注意下 : 如果在构造函数里面有方法的调用,那么请把调用放在继承之后。
BoundaryDrag.prototype.eleMove = function (x, y) {
x = x < 0 ? 0 : x;
this.ele.style.left = x + "px";
this.ele.style.top = y + "px";
}
var drag = new BoundaryDrag("#box");
</script>
</body>
</html>
2、es6继承(拖拽案例)
ES6 继承方式 : extends 关键字; 表示类的整体继承
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#box1,
#box2 {
width: 100px;
height: 100px;
background: skyblue;
position: absolute;
left: 0;
top: 0;
}
#box2 {
background: springgreen;
left: 200px;
}
</style>
</head>
<body>
<div id="box1"></div>
<div id="box2"></div>
<script>
class Drag {
constructor(selector) {
// 拖拽的元素;
this.ele = document.querySelector(selector);
this.bindEvent();
}
// tip : 方法分割是没有逗号的;
bindEvent() {
let self = this;
self.ele.onmousedown = function (evt) {
// 拖拽开启;
// console.log("拖拽开启");
let e = evt || event;
// 获取 offsetX 和 offsetY;
let { offsetX: x, offsetY: y } = e;
document.onmousemove = function (evt) {
let e = evt || event;
// 拖拽进行中;
// console.log("拖拽进行中");
// 为了让元素跟着鼠标点击的位置走而不是跟着鼠标的client 走;
self.eleMove(e.clientX - x, e.clientY - y);
}
}
document.onmouseup = function () {
// console.log("拖拽结束");
document.onmousemove = null;
}
}
eleMove(x, y) {
this.ele.style.left = x + "px";
this.ele.style.top = y + "px";
}
}
// ES6 继承方式 : extends 关键字; 表示类的整体继承;
// 有边界的拖拽;
class BoundaryDrag extends Drag {
// 继承之后更改分成两种 :
// 1. 构造函数里面的更改;
// 2. 原型对象上方法的更改;
constructor(selector) {
// 拖拽的元素;
// super相当于父级类的构造函数;
super(selector);
// 编写自己的代码;
console.log("带有边界检测的拖拽");
}
// 构造函数继承 :
// 1. 调用super; tip : 如果原本父类有参数,那必须传入参数;
// 2. 加入自己更新的代码;
// 1、在原型对象上方法的更改,更多的是使用覆盖的模式进行更改;
eleMove(x, y) {
x = x < 0 ? 0 : x;
this.ele.style.left = x + "px";
this.ele.style.top = y + "px";
}
// 2、注意以下 内部更新代码; 并不是适用于所有的开发场景;
eleMove(x, y) {
// 添加边界检测功能;
x = x < 0 ? 0 : x;
// 表示调用父类的eleMove 原型方法;
super.eleMove(x, y);
}
}
let drg1 = new BoundaryDrag("#box1");
let drg2 = new BoundaryDrag("#box2");
</script>
</body>
</html>