js对象继承的5种方法和JS的5种设计模式

一、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)
  1. 构造函数继承
	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)
  1. 组合继承(伪经典继承)
  2. 寄生组合继承(经典继承)
  3. 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()
  1. 发布订阅模式
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)

发布订阅模式与观察者模式的关系
其实这两种模式不过是实现上的差异,发布订阅模式多了个事件池。

其实说不同也不同(间接通知与直接通知),说相同也相同(都是发布更新,获取更新的过程)。个人更愿意将它们理解为同一种模式的不同实现。

如果以结构来分辨模式,发布订阅模式相比观察者模式多了一个中间件订阅器,
所以发布订阅模式是不同于观察者模式的;
如果以意图来分辨模式,他们都是实现了对象间的一种一对多的依赖关系,
当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知,
并自动更新,那么他们就是同一种模式,
发布订阅模式是在观察者模式的基础上做的优化升级
—

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值