一、JS对象继承的方法
1、原型链继承
// 原型链继承
// 定义一个构造函数
function Person() {
this.name = '构造函数的name' // 属性
// 实例
this.sleep = function () {
console.log(this.name + '吃饭')
}
}
// 原型方第一种 原型链继承
// 创建子类、添加子类属性。
function arrange(name) {
this.name = name;
this.goShop = function (food) {
console.log(name + '叫你去买' + food)
}
}
// 将父类实例赋值给子类原型对象
arrange.prototype = new Person();
console.log('原型继承', arrange.prototype.name)
- 构造函数继承
function Animal(age,color){
this.age = age || 12
this.color = color
}
function Cat(name){
Animal.call(this, 66, 'red');
this.name = name || 'tom'
}
var cat = new Cat();
console.log( 'cat---',cat.name)
- 组合继承(伪经典继承)
- 寄生组合继承(经典继承)
- es6的extends类继承
// es6的extends类继承
// 创建一个对象, class继承多态,面向对象的特性
class Person {
constructor(name) { // ES6 的类主要是通过 constructor 来实现构造函数的,作用:传参
this.name = name
}
say() {
console.log(this.name)
}
}
class Student extends Person {
constructor(name, id) {
super(name); // super主要是用来调用父亲的构造函数的
this.id = id;
}
say1() {
console.log(this.name, this.id)
}
}
let newStudent = new Student('xiaoxiao', 18)
console.log('student', newStudent)
打印:Student {name: ‘xiaoxiao’, id: 18}
二、JS涉及模式
1、工厂模式
类似于现实生活中的工厂可以陈胜大量相似的商品,去做同样的事情,实现同样的效果。
原理 将原始方法封装到函数中,并返回这个对象。
优点:能解决多个相似问题。
缺点:对象类型不知道,因为typeof返回结果都为object。
function Animal(args) {
var obj = new Object();
obj.name = args.name;
obj.color = args.color;
obj.getInfo = function() {
console.log(obj.name + "; " + obj.color)
}
return obj;
}
var cat = Animal({name: 'cat', color: 'yellow'});
var dog = Animal({name: 'dog', color: 'black'});
cat.getInfo();
dog.getInfo();
console.log(typeof cat);
console.log(typeof dog);
//cat; yellow
//dog; black
//object
//object
2、构造函数模式
原理:在构造函数内使用this关键字,创建属性和方法。在用new关键词创建实例,通过传参实现不同的实例。
优点 可以识别对象类型
缺点 构造函数会重复生成函数,为每个对象都创建独立的函数版本。
function Car(color, speed, price) {
this.color = color;
this.speed = speed;
this.price = price;
this.showColor = function() {
console.log(this.color);
}
}
var car1 = new Car('yellow', '100', 100000);
var car2 = new Car('red', '150', 1300000);
console.log(car1,car2);
console.log(car1 instanceof Car) //true
//Car {color: "yellow", speed: "100", price: 100000, showColor: ƒ}
//color: "yellow"
//price: 100000
//showColor: ƒ ()
//speed: "100"
//__proto__: Object
//Car {color: "red", speed: "150", price: 1300000, showColor: ƒ}
//color: "red"
//price: 1300000
//showColor: ƒ ()
//speed: "150"
//__proto__: Object
3、单例模式
只能被实例化一次
var Single = (function() {
var instance;
function init() {
//定义私有的方法和属性
return {
//定义共有的方法和属性
}
}
return {
//获取实例
getInstance: function() {
if(!instance) {
instance = init();
}
return instance;
}
}
})()
var obj1 = Single.getInstance();
var obj2 = Single.getInstance();
console.log(obj1 === obj2)//true
示例1:类似于广告弹框的模式
<body>
<div id="box">盒子</div>
<scrpt>
var createWindow = (function(){
var div;
return function(){
if(!div) {
div = document.createElement("div");
div.innerHTML = "我是弹窗内容";
div.style.display = 'none';
document.body.appendChild(div);
}
return div;
}
})();
document.getElementById("box").onclick = function(){
// 点击后先创建一个div元素
var win = createWindow();
win.style.display = "block";
}
</script>
</body>
示例2:如在网页中,点击按钮,添加(显示)一个遮罩层(需求:得到遮罩效果),可以第一次点击添加,以后的点击按钮,将遮罩显示出来就行,不需要重复添加遮罩层。
<style type="text/css">
.zhezhao{
width: 100%;
height:100%;
position:absolute;
left: 0;
top: 0;
background-color: rgba(0,0,0,.3);
}
button{
position: relative;
z-index: 2;
}
</style>
<button>显示</button>
<!-- <div class="zhezhao"></div> -->
<script>
(function(){
var btn=document.getElementsByTagName("button")[0];
var zhezhao;
function zhezhaoDis(){
btn.onclick=function(){
if(!zhezhao){
zhezhao=document.createElement("div");
zhezhao.className="zhezhao";
document.body.appendChild(zhezhao);
}else{
show();
}
function show(){
zhezhao.style.display="block";
}
}
}
window.zhezhaoDis=zhezhaoDis;
})();
zhezhaoDis();
</script>
4、观察者模式
VUE的响应式原理,就是使用的该模式
观察模式
let list = {
arr:[],
// 收集依赖的
addDeps: function(fn){
this.arr.push(fn)
console.log('添加依赖', this.arr)
},
// 对收集依赖做的处理--通知----notify是发布者
notify: function(){
console.log('通知')
this.arr.forEach(fn =>{
fn()
})
}
}
var fn1 = function(){
console.log('11')
}
var fn2 = function(){
console.log('22')
}
list.addDeps(fn1) // fn1观察者
list.addDeps(fn2) // fn1观察者
list.notify()
- 发布订阅模式
class Event {
constructor() {
this.eventEmitter = {};
}
// 订阅
on(type, fn) {
if (!this.eventEmitter[type]) {
this.eventEmitter[type] = [];
}
this.eventEmitter[type].push(fn);
console.log('111', this.eventEmitter)
}
// 取消订阅
off(type, fn) {
if (!this.eventEmitter[type]) {
return;
}
this.eventEmitter[type] = this.eventEmitter[type].filter((event) => {
return event !== fn;
});
console.log('取消', this.eventEmitter)
}
// 发布
emit(type) {
if (!this.eventEmitter[type]) {
return;
}
this.eventEmitter[type].forEach((event) => {
event();
});
}
}
let event = new Event();
console.log(event)
let fn = function(){
console.log('111')
}
event.on('on', fn)
event.emit('on')
event.off('on', fn)
发布订阅模式与观察者模式的关系
其实这两种模式不过是实现上的差异,发布订阅模式多了个事件池。
其实说不同也不同(间接通知与直接通知),说相同也相同(都是发布更新,获取更新的过程)。个人更愿意将它们理解为同一种模式的不同实现。
如果以结构来分辨模式,发布订阅模式相比观察者模式多了一个中间件订阅器,
所以发布订阅模式是不同于观察者模式的;
如果以意图来分辨模式,他们都是实现了对象间的一种一对多的依赖关系,
当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知,
并自动更新,那么他们就是同一种模式,
发布订阅模式是在观察者模式的基础上做的优化升级
—