浅拷贝和深拷贝、单例模式、适配器模式、观察者模式、组合模式、相关的面试题

这篇博客注释很少,主要展示的是代码 ,注释多的在前面的文章里

浅拷贝和深拷贝

<script>
  //浅拷贝 复制的是地址而非具体的值************************
  let obj1 = { a: 1, b: 2 };
  let obj2 = obj1;
  obj2.a = 11;
  console.log(obj1);   // {a: 11, b: 2}
  //深拷贝************************************
    let obj1 = { a: 1, b: 2 };
  let obj2 = {};
  for (let i in obj1) {
    obj2[i] = obj1[i];
  }
  obj2.a = 11;
  console.log(obj1);   // {a: 1, b: 2}

  //demo***********************************
  let obj1 = { a: [1], b: 2 };
  let obj2 = {};
  // 方法一********************
  for (let i in obj1) {
    obj2[i] = obj1[i];
  }
  console.log(obj2);
  obj2.a[0] = 11;//会有影响,会随着赋值改变而改变
  console.log(obj1);

  // 方法二*******************
  Object.assign(obj2, obj1);
  obj2.a[0] = 11;//会有影响
  console.log(obj1);

  // 方法三*******************
  function deepCopy(obj) {
    // if中的Array不能改成Object,因为数组也是一个对象
    //instanceof判断类型,结果为布尔值
    if (obj instanceof Array) {
      var newObj = [];
    } else {
      var newObj = {};
    }

    for (let i in obj) {
      if (typeof obj[i] == "object") {
        newObj[i] = deepCopy(obj[i]);
      } else {
        newObj[i] = obj[i];
      }
    }

    return newObj;
  }

  let obj2 = deepCopy(obj1);

  // 方法四********************
  // 先将其转化为字符串斩断其地址数据类型的链接,然后再转回原类型
  // 只不过不用定义let obj2={}; 
  let obj2 = JSON.parse(JSON.stringify(obj1));
  console.log(obj2);
  obj2.a[0] = 11;
  console.log(obj1);  // {a: Array(1), b: 2}
                      //    a: [11]
                      //    b: 2
                      //   __proto__: Object
</script>

单例模式

<!--保证一个类只有一个实例,并提供一个访问它的全局访问点-->

    <script>
      /*   function Foo() {}
      let foo = new Foo(); */
      let singleTon = (function () {
        let _instance = null;
        function Foo() {
          this.prop = "";
        }

        return {
          getInstance: function () {
            if (!_instance) {
              _instance = new Foo();
            }
            return _instance;
          },
        };
      })();

      console.log(singleTon.getInstance() == singleTon.getInstance());
    </script>

适配器模式

<!--将一个类(对象)的接口(方法或者属性)转化成另外一个接口以满足用户需求,使类(对象)之间接口的不兼容问题通过适配器得以解决。-->
    <script>
      //参数适配
      function foo(a, b, c, d) {}

      var data = {};
      //适配器
      function _adapter(obj) {
        foo(obj.a, obj.b, obj.c, obj.d);
      }
      _adapter(data);

      //************************************************
      function foo(options) {
        var defaults = {
          a: 1,
          b: 2,
          c: 3,
          d: 4,
        };

        var _adapter = {};
        for (let i in defaults) {
          _adapter[i] = options[i] || defaults[i];
        }

        //后续的代码就用_adpater
      }

      foo({ a: 11, c: 33 });

      //接口适配******************************************

      function BaiduMap() {}
      BaiduMap.prototype.show = function () {
        console.log("显示百度地图");
      };
      function GoogleMap() {}
      GoogleMap.prototype.display = function () {
        console.log("显示谷歌地图");
      };

      //适配器
      GoogleMap.prototype.show = function () {
        this.display();
      };

      function render(map) {
        map.show();
      }
      var baiduMap = new BaiduMap();
      render(baiduMap);
      var googleMap = new GoogleMap();
      render(googleMap);
    </script>

观察者模式

<!--观察者模式(发布-订阅模式):其定义对象间一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。-->
<script>
  var observer = {
    on: function (eventName, callback) {
      //订阅(注册,监听,添加)事件
      // eventHandles随便起的名字
      if (!this.eventHandles) {
        this.eventHandles = {};
      }

      if (this.eventHandles[eventName]) {
        this.eventHandles[eventName].push(callback);
      } else {
        this.eventHandles[eventName] = [callback];
      }
    },
    emit: function (eventName) {
      //发布 (触发)
      if (this.eventHandles[eventName]) {
        for (var i = 0; i < this.eventHandles[eventName].length; i++) {
          this.eventHandles[eventName][i]();
        }
      }
    },
    remove: function (eventName, callback) {
      //移除
      if (this.eventHandles[eventName]) {
        for (var i = 0; i < this.eventHandles[eventName].length; i++) {
          if (this.eventHandles[eventName][i] == callback) {
            this.eventHandles[eventName].splice(i, 1);
          }
        }
      }
    },
  };
  //个人中心  购物车  消息
  function personalCenter() {
    console.log("个人中心发生改变");
  }
  function cart() {
    console.log("购物车发生改变");
  }
  function message() {
    console.log("消息模块发生改变");
  }
  observer.on("loginSuccess", personalCenter);
  observer.on("loginSuccess", cart);
  observer.on("loginSuccess", message);

  observer.remove("loginSuccess", message);

  observer.emit("loginSuccess");
</script>

组合模式

<!--组合模式又称部分-整体模式,将对象组合成树形结构以表示“部分整体”的层次结构-->
<script>
  function Ticket() {}
  Ticket.prototype.create = function () {
    console.log("创建票务订单");
  };

  function Hotel() {}
  Hotel.prototype.create = function () {
    console.log("创建酒店订单");
  };

  function Order() {
    this.orders = [];
  }
  Order.prototype.add = function (order) {
    this.orders.push(order);
    return this;
  };
  Order.prototype.create = function () {
    for (let i = 0; i < this.orders.length; i++) {
      this.orders[i].create();
    }
  };

  let order = new Order();
  order.add(new Ticket()).add(new Ticket()).add(new Hotel()).create();
</script>

面试题

将on和emit里的代码写出来 从而实现后面的结果

<script type="text/javascript">
  //面试题
  var Event = {
    // 通过on接口监听事件eventName
    // 如果事件eventName被触发,则执行callback回调函数
    on: function (eventName, callback) {
      //你的代码 注册事件
      // obj随便命名的
      if (!this.obj) {
        //如果没有添加过保存事件名和回调函数的对象,添加一下
        Object.defineProperty(this, "obj", {
          value: {},
          enumerable: false,
        });
      }
      if (this.obj[eventName]) {
        this.obj[eventName].push(callback);
      } else {
        this.obj[eventName] = [callback];
      }
    },
    //触发事件 eventName
    emit: function (eventName) {
      //console.log(this.obj);
      //你的代码
      if (this.obj[eventName]) {
        for (var i = 0; i < this.obj[eventName].length; i++) {
          this.obj[eventName][i](arguments[1]);
        }
      }
    },
  };

  // 测试1

  Event.on("test", function (result) {
    console.log(result);
  });
  Event.on("test", function () {
    console.log("test");
  });

  Event.emit("test", "hello world"); // 输出 'hello world' 和 'test'

  // 测试2
  var person1 = {};
  var person2 = {};

  Object.assign(person1, Event);
  Object.assign(person2, Event);

  person1.on("call1", function () {
    console.log("person1");
  });

  person2.on("call2", function () {
    console.log("person2");
  });

  person1.emit("call1"); // 输出 'person1'
  person1.emit("call2"); // 没有输出
  person2.emit("call1"); // 没有输出
  person2.emit("call2"); // 输出 'person2'
</script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值