一、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)
发布订阅模式与观察者模式的关系
其实这两种模式不过是实现上的差异,发布订阅模式多了个事件池。
其实说不同也不同(间接通知与直接通知),说相同也相同(都是发布更新,获取更新的过程)。个人更愿意将它们理解为同一种模式的不同实现。
如果以结构来分辨模式,发布订阅模式相比观察者模式多了一个中间件订阅器,
所以发布订阅模式是不同于观察者模式的;
如果以意图来分辨模式,他们都是实现了对象间的一种一对多的依赖关系,
当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知,
并自动更新,那么他们就是同一种模式,
发布订阅模式是在观察者模式的基础上做的优化升级
—

本文介绍了JavaScript中的原型链继承、构造函数继承、类继承(包括ES6的extends)以及工厂模式、构造函数模式、单例模式、观察者模式和发布订阅模式。这些技术展示了面向对象编程的实践和设计模式在实际项目中的运用。

被折叠的 条评论
为什么被折叠?



