zoukankan      html  css  js  c++  java
  • JS面向对象组织代码

    JS本身不存在类的概念,它对于继承的判定有时非常混乱,当然这并不影响我们以面向对象的思维去编程。

    例如我们有两个类A类B类,我们想让B类继承A类,在python中可以轻而易举的实现,在JS中需要一种折中法

            function A() {
    
            }
    
            A.prototype.hello = function() {
                console.log(1)
            }
    
            function B() {
    
            }
            B.prototype = new A();
            (new B()).hello()

    B的原型对象指向了A的实例

            // 在子类需要继承父类属性的情况下需要用这种方法
            function A(a) {
                this.a = a;
            }
    
            A.prototype.hello = function() {
                console.log(this.a)
            }
    
            function B(a, b) {
                this.constructor.apply(this, arguments)
                this.b = b;
            }
            B.prototype = new A();
            (new B(1, 2)).hello()
    1        var obj = {
    2            a : 1,
    3            b : 2,
    4            c : false
    5        }
    6
    7        console.log("a" in obj);    //true
    8        console.log("b" in obj);    //true
    9        console.log("c" in obj);    //true
            console.log("d" in obj);    //false

    in不仅仅检测是对象自己有没有这个属性,如果原型链上有这个属性,那么也会返回true。整个原型链如果没有这个属性,就返回false。也就是说,in操作符会进行原型链查找。

    for in 这个循环,会把原型链上所有的可枚举的属性列出来

    hasOwnProperty方法则是只检测自己是否有这个属性

    值得说的是instanceof这个运算符的机理,它会查找原型链所有原型,只有要构造函数指向了原型链上的任意原型它就会返回true

            function A() {
    
            }
    
            function B() {
    
            }
    
            B.prototype = new A();
            console.log(new B() instanceof B)
    
            // 此时B的原型已经是A的实例,在原型链层面上没有任何逻辑可以证明B的实例的构造函数是B但是结果是true
    
            // 再举个例子
    
            function C() {}
            C.prototype = Array.prototype;
            var arr = [];
    
            console.log(arr instanceof C)
                // 返回的也是true,如果说上一个例子B的实例和构造函数的关系是真实的,那么构造函数C和arr并不存在任何关系
                // 只是C的原型指向了Array的原型,但instanceof的意义是证明arr 是 C 的实例,实际并不是

    面向对象对于代码的组织结构更加清晰例如,贪吃蛇小游戏

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <style>
        table,
        tr,
        td {
            border: 1px solid #000;
            border-collapse: collapse;
        }
        
        td {
             18px;
            height: 18px;
        }
        
        .red {
            background-color: red;
        }
        
        .blue {
            background-color: blue;
        }
    </style>
    
    <body>
        <table id="snake">
        </table>
    
    
        <script>
            // 面向对象的思维做游戏,首先确认需要的类
            // 地图类
            // 蛇类
            // 食物类
            // 创建地图类
    
            function Map() {
                this.data = [];
                this.timer = null;
                this.dom = document.getElementById('snake');
                this.init();
            }
    
            // 地图类有一个初始化的方法
    
            Map.prototype.init = function() {
                    var rowArr;
                    var tr;
                    var td;
                    for (var row = 0; row < 40; row++) {
                        rowArr = [];
                        tr = document.createElement('tr');
                        this.dom.appendChild(tr);
                        for (var col = 0; col < 40; col++) {
                            td = document.createElement('td');
                            tr.appendChild(td);
                            rowArr.push(td);
                        }
                        this.data.push(rowArr)
                    }
                }
                // Map有一个清空画布的方法
            Map.prototype.clear = function() {
                for (var i = 0; i < 40; i++) {
                    for (var j = 0; j < 40; j++) {
                        this.data[i][j].className = "";
                    }
                }
            };
    
    
            // 创建蛇类
            function Snake() {
                this.location = [{
                    'x': 5,
                    'y': 10
                }, {
                    'x': 5,
                    'y': 9
                }, {
                    'x': 5,
                    'y': 8
                }, {
                    'x': 5,
                    'y': 7
                }, {
                    'x': 5,
                    'y': 6
                }, {
                    'x': 5,
                    'y': 5
                }, ];
                this.direction = 'right';
                this.isEnd = false;
                this.render();
                this.bindEvenet();
            }
    
    
            // 蛇有一个渲染方法
            Snake.prototype.render = function() {
                var tempDom;
                for (var i = 0; i < this.location.length; i++) {
                    if (this.isEnd) {
                        break;
                    }
                    tempDom = map.data[this.location[i].x][this.location[i].y];
                    tempDom.className = 'blue'
                }
            };
    
            // 蛇有一个更新自己的函数
            Snake.prototype.update = function() {
                // 蛇头向用户输入方向加1蛇尾减1
                this.location.pop();
                // 随时都要监听用户输入了什么方向
                switch (this.direction) {
                    case 'left':
                        this.location.unshift({
                            'x': this.location[0].x,
                            'y': this.location[0].y - 1,
                        });
                        break;
                    case 'top':
                        this.location.unshift({
                            'x': this.location[0].x - 1,
                            'y': this.location[0].y,
                        });
                        break;
                    case 'right':
                        this.location.unshift({
                            'x': this.location[0].x,
                            'y': this.location[0].y + 1,
                        });
                        break;
                    case 'bottom':
                        this.location.unshift({
                            'x': this.location[0].x + 1,
                            'y': this.location[0].y,
                        });
                        break;
                }
                this.check();
            };
    
            // 给蛇类绑定一个方向事件
            Snake.prototype.bindEvenet = function() {
                var self = this;
                document.onkeydown = function(event) {
                    event = event || window.event;
                    switch (event.keyCode) {
                        case 37:
                            // 蛇头只有一个方向,假设当前方向为左
                            // 那么我们蛇的X值是-1的,如果这时候用户输入右
                            // 那么X值变为 + 1,此时就会出现bug也就是短暂的重合
    
                            if (self.direction == 'right') {
                                return;
                            }
                            self.direction = 'left'
                            break;
                        case 38:
                            if (self.direction == 'bottom') {
                                return;
                            }
                            self.direction = 'top'
                            break;
                        case 39:
                            if (self.direction == 'left') {
                                return;
                            }
                            self.direction = 'right'
                            break;
                        case 40:
                            if (self.direction == 'top') {
                                return;
                            }
                            self.direction = 'bottom'
                            break;
                    }
                };
    
            };
            // 蛇有一个吃食物的方法
            Snake.prototype.eatFood = function() {
                // 蛇头碰到食物
                if (this.location[0].x == food.x && this.location[0].y == food.y) {
                    // 当我们碰到食物时重新计算位置
                    food.change();
                    // 蛇头加1
                    switch (this.direction) {
                        case 'left':
                            this.location.unshift({
                                'x': this.location[0].x,
                                'y': this.location[0].y - 1,
                            });
                            break;
                        case 'top':
                            this.location.unshift({
                                'x': this.location[0].x - 1,
                                'y': this.location[0].y,
                            });
                            break;
                        case 'right':
                            this.location.unshift({
                                'x': this.location[0].x,
                                'y': this.location[0].y + 1,
                            });
                            break;
                        case 'bottom':
                            this.location.unshift({
                                'x': this.location[0].x + 1,
                                'y': this.location[0].y,
                            });
                            break;
                    }
                }
            };
            //  蛇有要检测是否撞到自己或边缘
            Snake.prototype.check = function() {
                if (snake.location[0].x < 0 || snake.location[0].x > 39 || snake.location[0].y < 0 || snake.location[0].y > 39) {
                    this.isEnd = true;
                }
                for (var i = 0; i < this.location.length - 1; i++) {
                    if (this.location[0].x == this.location[i + 1].x && this.location[0].y == this.location[i + 1].y) {
                        this.isEnd = true
                    }
                }
            };
            // 食物类
            function Food() {
                this.x = NaN;
                this.y = NaN;
                this.change();
            };
            // 食物类有个方法,计算食物的位置
            Food.prototype.change = function() {
                // 食物不能和蛇重合
                this.x = parseInt(Math.random() * 40)
                this.y = parseInt(Math.random() * 40)
                for (var i = 0; i < snake.location.length; i++) {
                    if (this.x == snake.location[i].x && this.y == snake.location[i].y) {
                        food.create();
                    }
                }
            };
    
            // 食物类有一个渲染方法
            Food.prototype.render = function() {
                map.data[this.x][this.y].className = 'red';
            };
            var map = new Map();
            var snake = new Snake();
            var food = new Food();
    
            var timer = setInterval(function() {
                // 清空画布
                map.clear();
                // 我们将其想象成canvas现在我们自己建的画布每秒都在重新绘制
                // 清空画布后我们需要渲染蛇与食物
                snake.update();
                snake.eatFood();
                snake.render();
                food.render();
                if (snake.isEnd) {
                    clearInterval(timer)
                    alert('GAME OVER')
                }
            }, 300);
            // 当然这里只是最简单的实现,如果你想同时产生多个不同大小的食物,根据蛇身体大小加速等等,都可以自由实现
            // 比如要产生多个食物,可以给食物类添加食物地图...
            // 面向对象的思维就是可以根据人类的思维无限延伸,理论上是这样,创造性和协调性更强
        </script>
    
    </body>
    
    </html>
  • 相关阅读:
    《计算机图形学-基于3D图形开发技术》读书笔记
    【转】OpenGL和D3D 矩阵对比
    【转】D3D中详细拾取操作
    根据点坐标改变字体显示位置
    静态常量和常量在类中的初始化
    MFC单文档中使用D3D9
    单文档切换OpenGL视图
    超大地形的处理 (Terrain Visualization)【转自知乎】
    又出现这种问题。。。
    属性
  • 原文地址:https://www.cnblogs.com/tengx/p/12360891.html
Copyright © 2011-2022 走看看