当前位置: 首页 > news >正文

【JavaScript】原型链 prototype 和 this 关键字的练习(老虎机)

这个老虎机练习主要考察JavaScript中的原型链(prototype)和this关键字的使用。


主要思路

  1. 创建三个轮盘(reels)实例:我们需要创建3个独立的轮盘对象,它们都委托(delegate)到基础的reel对象。这可以通过Object.create(reel)来实现,创建新对象并将其原型指向reel

  2. 实现display()方法:这是最复杂的部分,需要显示3×3的网格:

    • 每个轮盘需要显示三个位置:当前位置、上方位置和下方位置
    • 行显示(水平方向):以"|"分隔的三个轮盘符号
    • 列显示(垂直方向):每个轮盘的三个位置(上中下)

实现代码

function randMax(max) {
    return Math.trunc(1E9 * Math.random()) % max;
}

var reel = {
    symbols: [
        "♠", "♥", "♦", "♣", "☺", "★", "☾", "☀"
    ],
    spin() {
        if (this.position == null) {
            this.position = randMax(
                this.symbols.length
            ); 
        }
        this.position = (
            this.position + 100 + randMax(100)
        ) % this.symbols.length;
    },
    display() {
        if (this.position == null) {
            this.position = randMax(
                this.symbols.length
            );
        }
        return this.symbols[this.position];
    }
};

var slotMachine = {
    reels: [
        Object.create(reel),
        Object.create(reel),
        Object.create(reel)
    ],
    spin() {
        this.reels.forEach(reel => {
            reel.spin();
        });
    },
    display() {
        // 获取每个轮盘上方、当前和下方的符号
        var lines = [];
        
        // 创建三行(上、中、下)
        for (let linePos = -1; linePos <= 1; linePos++) {
            let line = this.reels.map(reel => {
                // 创建一个临时对象,委托到reel,但拥有自己的position
                var slot = Object.create(reel);
                
                // 调整position以显示上方/当前/下方的符号
                slot.position = (
                    (reel.position + linePos) + 
                    reel.symbols.length
                ) % reel.symbols.length;
                
                return slot.display();
            });
            
            lines.push(line.join(" | "));
        }
        
        // 打印结果
        console.log(lines.join("\n"));
    }
};

slotMachine.spin();
slotMachine.display();

slotMachine.spin();
slotMachine.display();


代码解析

  • 循环创建三行:使用-101作为偏移量,分别表示上、中、下行

  • 显示每个位置的符号

    • 为每个位置创建一个临时对象(使用Object.create(reel)
    • 调整临时对象的position属性,考虑到循环(使用模运算)
    • 调用临时对象的display()方法获取符号
  • 处理循环边界问题:当计算上方位置(特别是当前位置为0时),需要加上reel.symbols.length来确保结果为正,然后再取模

  • 格式化输出:组合所有符号,map生成的行数组用"|“分隔转换成字符串后加入lines数组,lines数组用换行符”\n"分隔转换成字符串。

  • spin()方法有两个主要作用:

    1. 初始化位置:如果轮盘的position属性为null(比如第一次使用时),它会为轮盘设置一个初始随机位置。

    2. 改变轮盘位置:每次调用spin()都会使轮盘旋转一定数量的位置(至少100个位置加上0-99的随机数),然后通过取模确保最终位置在有效范围内。

      在示例代码中:

      slotMachine.spin();
      slotMachine.display();
      // 显示第一组结果
      
      slotMachine.spin();
      slotMachine.display();
      // 显示第二组结果
      

      两次结果不同,正是因为中间调用了spin()方法,改变了每个轮盘的位置。如果删除第二个spin()调用,两次display()会显示完全相同的结果。

      所以spin()方法是整个老虎机机制的核心部分之一,它模拟了真实老虎机拉杆后轮盘旋转的过程,而这个旋转直接决定了最终显示的符号组合。

  • reel原型对象

    1. reels数组中的对象

      reels: [
          Object.create(reel),
          Object.create(reel),
          Object.create(reel)
      ]
      

      这里创建了三个独立的对象,每个都作为slotMachine的一个轮盘。这些对象在整个slotMachine的生命周期中持续存在,并且每个都维护自己的position属性状态。当我们调用slotMachine.spin()时,这三个对象的position属性会被更新。

    2. display()方法中的临时对象

      var slot = Object.create(reel); // 这个是个临时对象,不是reels中的元素
      

      这是在display()方法内部创建的临时对象,它在每次显示时创建,用完即丢弃。这个临时对象不是用来替代轮盘的,而是用来临时保存修改后的位置,以便显示上方或下方的符号,而不影响原始轮盘的position属性

      理解这一点很关键:slot是通过原型链委托到reel对象的,而reels数组中的每个元素是通过原型链委托到同一个reel对象的独立对象。

      因此,它们在内存中是完全不同的对象,只是共享相同的原型。这种结构让我们能够在不改变原始轮盘位置的情况下,显示每个轮盘的上方、当前和下方位置的符号。

  • 理解参数reel的来源:

    1. this.reels.map(function getSlot(reel){...}) 中的reel参数是map方法传入的,它代表的是this.reels数组中的每个元素,也就是我们在slotMachine初始化时创建的那三个轮盘对象。

    2. 然后,我们基于这个轮盘对象创建一个临时对象:var slot = Object.create(reel),这个临时对象的原型是当前遍历到的轮盘对象,而不是原始的reel对象。

    3. 这样,我们可以通过reel.position访问到当前轮盘的位置,并在临时对象中设置调整后的位置:slot.position = ...

    简单来说,这里存在三层委托关系:

    • slot对象委托到reels数组中的特定轮盘对象
    • 那个轮盘对象又委托到原始的reel对象
    • 当我们调用slot.display()时,会使用slot自己的position,但方法本身是从reel原型继承的

http://www.dtcms.com/a/112062.html

相关文章:

  • 安当TDE透明加密:构建跨地域文件服务器安全传输的“双重保险“
  • VBA中类的解读及应用第二十二讲:利用类判断任意单元格的类型-5
  • C语言:3.31
  • 【YOLO系列(V5-V12)通用数据集-火灾烟雾检测数据集】
  • 大模型学习四:‌DeepSeek Janus-Pro 多模态理解和生成模型 本地部署指南(折腾版)
  • 七均线策略思路
  • Mac VM 卸载 win10 安装win7系统
  • Win7下安装高版本node.js 16.3.0 以及webpack插件的构建
  • Apache Camel指南-第四章:路由径构建之异常处理
  • 如何使用 IntelliJ IDEA 开发命令行程序(或 Swing 程序)并手动管理依赖(不使用 pom.xml)
  • 从飞机的状态矩阵A阵求运动模态的特征根、求传递函数矩阵
  • NOIP2013提高组.华容道
  • 从菜鸟到高手的提示词优化指南‌
  • Muduo网络库介绍
  • Sensodrive力控关节模组SensoJoint:TÜV安全认证助力机器人开发
  • 主机和虚拟机间的网络通信
  • LeetCode算法题(Go语言实现)_29
  • JavaScript重难点突破:事件循环
  • 基于 Python 的自然语言处理系列(70):检索增强生成(RAG)
  • Go语言-初学者日记(八):构建、部署与 Docker 化
  • 《操作系统真象还原》第五章(2)——启用内存分页机制
  • 蓝桥杯15届 宝石组合
  • 【HC-05蓝牙模块】基础AT指令测试
  • 思维链 Chain-of-Thought(COT)
  • 视野,,地面覆盖,重叠需求,FPS,飞行速度等的计算公式
  • LLM面试题五
  • JVM 有哪些垃圾回收器
  • 【2023】ORIGIN或MATLAB 颜色图,等高图,颜色条——需要拟合补全中间的颜色
  • 算法--最长上升子序列
  • 京东零售首次公开!6B参数时序大模型实现20000款商品自动补货预测