JS面向对象介绍
首先面向对象是什么?为什么要使用面向对象。
因为JavaScript对每个创建的对象都会自动设置一个原型(谷歌火狐中是proto),指向它的原型对象prototype,举个例子:
function persoon(){}
那么person的原型链就是:
person(proto) > Function.prototype(proto) > Object.prototype
所以最终的结果都是指向原型对象,就称为面向对象
那么问题来了,怎么面向对象呢?实际上就是在问怎么创建面向对象,创建面向对象有哪几种方法。
方法一:工厂模式创建
本质:就是在函数内部创建一个对象,每次调用的时候传入不同的参数,然后返回这个对象
function Factory(name, age) {
let obj = {};
obj.name = name;
obj.age = age;
obj.sayHi = function () {
console.log("hello world");
}
return obj;
}
let obj = Factory("小小荧", 22);
console.log(obj);
方法二:构造函数方式创建
本质:跟工厂模式的区别就是函数中用this替换了return的作用,还有一个区别就是创建对象的时候是new一个对象
function Person(name, age) {
this.name = name;
this.age = age;
this.sayHi = function () {
console.log(this.name, this.age);
}
}
let person1 = new Person("小小荧", 22);
let person2 = new Person("哈哈哈", 23);
console.log(person1);
console.log(person2)
方法三:原型方式的创建
本质:先通过创建一个函数Function,然后在通过Function.prototype上添加属性和方法,在new一个Function这种方式一个对象
function Person(name, age) {
this.name = name;
this.age = age;
this.say = function(){
console.log("hello world");
}
}
// 在构造函数原型中写共享的属性和方法
Person.prototype.sing = function(){
console.log("唱歌")
}
let person1 = new Person("小小荧", 22);
console.log(person1);
person1.say();
person1.sing();
let person2 = new Person("哈哈哈", 23);
console.log(person2)
person2.say();
person2.sing()
那我们如何证明一下原型上的sing方法是共享的呢在上图中的person1和person2下的proto下的都存在sing方法,person1和person2调用sing方法的时候会在自己的实例对象中查找sing方法如果没有就回去prototype中查找,查找到我们就调用该方法,如果找到顶层对象都没有找到这个方法就是返回undefined。所以perosn1和person2调用sing的时候调用的是同一个sing方法,这就是证明了sing是方法共享的。
面向对象案例演示
tab选项卡面向对象案例
<!DOCTYPE html>
<!--
* @Descripttion:
* @version:
* @Author: 小小荧
* @Date: 2020-03-17 21:30:55
* @LastEditors: 小小荧
* @LastEditTime: 2020-03-17 21:43:50
-->
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.container {
360px;
height: 277px;
border: 10px solid #000;
overflow: hidden;
margin: 0 auto;
}
.content {
height: 257px;
text-align: center;
line-height: 257px;
font-size: 100px;
position: relative;
}
.box {
100%;
height: 100%;
position: absolute;
background: #fff;
display: none;
}
button.active {
color: aliceblue;
background: black;
}
.box.active {
display: block;
z-index: 1;
}
</style>
</head>
<body>
<div class="container">
<div class="btns">
<button data-index="0" class="btn active">1</button>
<button data-index="1" class="btn">2</button>
<button data-index="2" class="btn">3</button>
</div>
<div class="content">
<div class="box active">1</div>
<div class="box">2</div>
<div class="box">3</div>
</div>
</div>
<script>
// 选项卡的构造函数
function Table() { }
// 初始化函数
Table.prototype.init = function (options) {
this.btns = this.$(options.btn);
this.boxs = this.$(options.box);
// 绑定事件
this.bindEvent();
}
// 选择器函数
Table.prototype.$ = function (seletor) {
// 返回元素节点
return document.querySelectorAll(seletor);
}
// 事件监听器函数
Table.prototype.bindEvent = function () {
// 循环节点
for (var i = 0; i < this.btns.length; i++) {
this.btns[i].addEventListener("mouseover", function (index) {
// 删除class类名
this.removeClassName();
// 添加class类名
this.addClassName(index);
}.bind(this, i));
}
}
// 删除class类名函数
Table.prototype.removeClassName = function () {
// 循环删除active的类名
for (var i = 0; i < this.btns.length; i++) {
this.btns[i].className = this.btns[i].className.replace(/s?active/, "");
this.boxs[i].className = this.boxs[i].className.replace(/s?active/, "");
}
}
// 添加class类名函数
Table.prototype.addClassName = function (index) {
// 给节点添加active的class类名
this.btns[index].className += " active";
this.boxs[index].className += " active";
}
var table = new Table();
table.init({
btn : ".btn",
box : ".box"
});
</script>
</body>
</html>
漫天萤火虫
<!DOCTYPE html>
<!--
* @Descripttion:
* @version:
* @Author: 小小荧
* @Date: 2020-03-17 21:44:07
* @LastEditors: 小小荧
* @LastEditTime: 2020-03-22 14:19:09
-->
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
body {
margin: 0;
padding: 0;
}
.container {
600px;
height: 400px;
background: #000000;
margin: 50px auto;
position: relative;
}
.disc {
display: block;
4px;
height: 4px;
background: #ffffff;
border-radius: 50%;
position: absolute;
top: 0;
left: 0;
opacity: 1;
border: 1px solid #ffffff
}
</style>
</head>
<body>
<div class="container">
</div>
<script src="./多属性运动.js"></script>
<script>
// 定义一个小圆点的构造函数
function Disc(options) {
this.init(options)
}
// 初识化的方法
Disc.prototype.init = function (options) {
// 这个就是初始化的时候这是一个计数的属性,后面可以用来判断就完成透明的切换
this.count = 0;
// 父盒子的宽度
this.box_width = options.box_width;
// 父盒子的高度
this.box_height = options.box_height;
// 父盒子
this.box_ele = options.box_ele;
// 创建节点
this.createEle();
}
// 生成随机坐标
Disc.prototype.randomPos = function () {
// x 坐标
this.x = Math.round(Math.random() * (this.box_width - this.disc_ele.offsetWidth));
// y坐标
this.y = Math.round(Math.random() * (this.box_height - this.disc_ele.offsetHeight));
}
// 创建每一个元素的函数
Disc.prototype.createEle = function () {
// 创建每一个小圆点的元素节点
this.disc_ele = document.createElement("span");
// 设置className
this.disc_ele.className = "disc";
// 像父盒子中追加元素节点
this.box_ele.appendChild(this.disc_ele);
// 获取随机的xy值
this.randomPos();
// 设置这个元素的xy值
this.disc_ele.style.left = this.x + "px";
this.disc_ele.style.top = this.y + "px";
// 创建完成之后我们就需要移动了
this.move(this.disc_ele);
}
// 执行运动函数
Disc.prototype.move = function (ele) {
// 我们默认opacity是0.6的透明度
var opacity = 0.6;
if (this.count % 2) {
// 如果运动的次数是奇数,我们就让这个透明度变为1
opacity = 1;
}
// 每次执行都需要count++
this.count++;
this.randomPos();
animate(ele, {
top: this.y,
left: this.x,
opacity: opacity
}, () => {
this.move(ele);
});
}
var box_ele = document.querySelector(".container");
var box_width = box_ele.offsetWidth;
var box_height = box_ele.offsetHeight;
//循环穿件元素节点
for (var i = 0; i < 80; i++) {
// 创建对象
var disc = new Disc({
box_ele: box_ele,
box_ box_width,
box_height: box_height
});
}
</script>
</body>
</html>
这个案例需要使用到运动函数请参考运动函数