JavaScript 基础理解三

0 阅读3分钟

设计到模式

设计模式 是软件开发中一套被反复验证、用于解决特定场景下通用问题的 “最佳实践模板”。它不是现成的代码,而是一种可复用的设计思路

根据设计,即是一种思想,模式相当于一种固定的模板,也就是从设计到模式。

1.遇到具体问题

遇到一个问题:页面中多次点击 “打开弹窗” 按钮,每次都会创建一个新的弹窗 DOM 节点,导致页面出现多个重复弹窗,既浪费资源又影响体验。

2. 设计思想(解决思路)

针对这个问题,思考出核心设计思想: “确保某个对象在程序生命周期内只有一个实例,重复调用时直接返回已存在的实例,而非新建” 。这个思想是抽象的 —— 它只规定了 “要做什么”,但没说 “具体怎么做”。

3. 模式模板(具象化实现)

基于这个设计思想,结合 JavaScript 的特性(闭包、立即执行函数),封装出一套可复用的 “模式模板“

思想是根,模式是果。设计模式的本质是「抽象设计思想」→「具象模式模板」的转化:思想解决 “为什么做”,模板解决 “怎么做”。这里就需要需结合业务场景灵活适配,避免僵化套用。

题目1:

外出打车,可选专车和快车,不同车价格不同,快车每公里1元,专车每公里2元,行程开始显示车辆信息,结束显示支付金额。

1.专车和快车有公共的特性,可以提取出来,车牌,颜色等

创建一个父类:Car

2.专车和快车有自己单独的价格属性

创建一个kuaiChe和zhuanche类,继承Car

3.行程是当前开始接单到结束状态

创建一个Trip类,有单独的行程方法

实现行程中的信息:

    class Car {
        
        constructor(number,name){
            
            this.number = number
            this.name = name
        
        }
    
    }
    
    class Kuaiche extends Car {
        
       constructor(number,name) {
       
           super(number,name)
           this.price =1
       }
    
    }

    class zhuanche extends Car{
         constructor(number,name) {
       
           super(number,name)
           this.price =2
       }
    
    }
    
    
    class Trip {
    
       constructor(car) {
          this.car = car
       }
       
       start(){
       
           console.log('行程开始'+this.car.name)
       }
       
       end(){
           console.log('行程结束,价格'+(this.car.price*10))
       
       }
    
    }
    
    let car = new KuaiChe(10291,'宝马')
    
    let trip = new Trip(car)
    trip.start()
    trip.end()
    
    
  • 第一步new KuaiChe(10291, '宝马') 创建实例:

    1. 调用 KuaiChe 的构造函数,先执行 super(number, name) → 调用父类 Car 的构造函数;
    2. Car 的构造函数给实例赋值 this.number = 10291this.name = '宝马'
    3. 回到 KuaiChe 的构造函数,给实例赋值 this.price = 1
    4. 最终 car 实例的结构是:{ number: 10291, name: '宝马', price: 1 }
  • 第二步new Trip(car) 创建行程实例:

    1. Trip 的构造函数接收第一步的 car 实例,并存为 this.car
    2. 此时 trip 实例的结构是:{ car: { number: 10291, name: '宝马', price: 1 } }
  • 第三步trip.start() / trip.end() 访问属性:

    1. this.car.name → 直接访问 trip 持有的 car 实例的 name 属性(这个属性是 KuaiChe 继承自 Car 并初始化的);

    2. this.car.price → 访问 KuaiChe 自身定义的 price 属性;

    3. 整个过程中,Trip 只是 “借用” 了 car 实例的属性,而非自己继承了 Car 的属性。

      class Car {
          constructor(number, name) { 
              this.number = number;
              this.name = name; 
          } 
          // 定义在Car原型上的方法
          getCarInfo() { 
              return `${this.name}(${this.number})`; 
              } 
      }
      
      class KuaiChe extends Car { 
          constructor(number, name){ 
              super(number, name); 
              this.price = 1;
             } 
          } 
          const car = new KuaiChe(10291, '宝马');
          // 访问原型链上的方法:car自己没有getCarInfo,就往上找Car的原型 
          console.log(car.getCarInfo()); // 输出:宝马(10291)
      
      
      
      

    当访问 car.getCarInfo 时,JS 引擎会先看 car 实例自己有没有 getCarInfo ,如果没有(比如你没在 Car 里定义),才会沿着原型链往上找父类 Car 的原型,这就是 “原型链查找”.