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 {
        width: 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>

原文地址:https://www.cnblogs.com/tengx/p/12360891.html

时间: 2024-08-09 17:03:31

JS面向对象组织代码的相关文章

如何编写可维护的面向对象JavaScript代码

能够写出可维护的面向对象JavaScript代 码不仅可以节约金钱,还能让你很受欢迎.不信?有可能你自己或者其他什么人有一天会回来重用你的代码.如果能尽量让这个经历不那么痛苦,就可以节省不少时 间.地球人都知道,时间就是金钱.同样的,你也会因为帮某人省去了头疼的过程而获得他的偏爱.但是,在开始探索如何编写可维护的面向对象JavaScript代码之前,我们先来快速看看什么是面向对象.如果已经了解面向对象的概念了,就可以直接跳过下一节. 什么是面向对象?  面向对象编程主要通过代码代表现实世界中的实

js面向对象的系列

在面向对象语言中如java,C#如何定义一个对象,通常是定义一个类,然后在类中定义属性,然后通过new 关键字来实例化这个类,我们知道面向对象有三个特点,继承.多态和封装.那么问题来了,在javaScript中如何定义一个类?在javaScript中如何定义类的属性?如何继承?带着这些问题开始我们的js面向对象之旅吧. 在js中如何定义类? js中是没有类的概念的,但是我们通常会用一个函数定义成一个类.funtion class1(){ //类的成员定义 } 这里class1既是一个函数也是一个

简单粗暴地理解js原型链--js面向对象编程

简单粗暴地理解js原型链--js面向对象编程 原型链理解起来有点绕了,网上资料也是很多,每次晚上睡不着的时候总喜欢在网上找点原型链和闭包的文章看,效果极好. 不要纠结于那一堆术语了,那除了让你脑筋拧成麻花,真的不能帮你什么.简单粗暴点看原型链吧,想点与代码无关的事,比如人.妖以及人妖. 1)人是人他妈生的,妖是妖他妈生的.人和妖都是对象实例,而人他妈和妖他妈就是原型.原型也是对象,叫原型对象. 2)人他妈和人他爸啪啪啪能生出一堆人宝宝.妖他妈和妖他爸啪啪啪能生出一堆妖宝宝,啪啪啪就是构造函数,俗

Meteor: 如何复用node.js包或代码

Meteor基于Node.js,但是却有自己的包管理系统(atmosphere)以及代码加载机制,且meteor是非异步的,这些都意味着,node.js包(npm package)和代码通常不能直接用于meteor程序. 这里分享三种方法以在meteor中复用node.js包和代码. meteorhacks:npm + meteorhacks:async npm+async是复用npm包最便捷的方式.meteor程序添加npm包之后,便可以在packages.json中声明包依赖,在程序中通过M

js面向对象程序设置——创建对象

<script type="text/javascript">            //工厂方式        //1.原始方式        /* var objCar=new Object();        objCar.name="劳斯莱斯";        objCar.color="blue";        objCar.showColor = function() {          alert(this.colo

js面向对象编程:如何实现方法重载

js中如何实现方法重载?这涉及到三个问题 1同名函数的调用问题 2函数中特殊的参数arguments 3如何利用arguments实现方法重载 1同名函数的调用问题 都知道在js中如果存在多个名称相同的函数,则调用实际每次都只使用最后一个,js其实是没有重载的,也就是说,如果定义了多个同名的函数,单参数不一样,在调用时,js不管参数个数,只管前后顺序 例如: function test1(arg1) { alert("参数1:"+arg1); } function test1(arg1

玩转JS系列之代码加载篇

从前我们这样写js <script type="text/javascript"> function a(){ console.log('a init');}function b(){ console.log('b init'); a(); } </script> 随着功能越来越多,我们开始把js分离,使用单独的js文件来写,然后使用下面的方式引入js <script src="a.js" type="text/javascr

js面向对象深入理解

js面向对象深入理解 ECMAScript 有两种开发模式:1.函数式(过程化),2.面向对象(OOP).面向对象的语言有一个标志,那就是类的概念,而通过类可以创建任意多个具有相同属性和方法的对象.但是,ECMAScript 没有类的概念,因此它的对象也与基于类的语言中的对象有所不同. 一.创建对象 创建一个对象,然后给这个对象新建属性和方法. var box = new Object(); //创建一个Object 对象 box.name = 'Lee'; //创建一个name 属性并赋值 b

js面向对象编程

1.js面向对象之对象 1.1js代码 <script> function hello(){ alert("hi!"); } //使用prototype属性为类添加属性和方法 hello.prototype={ name:"lihua", say:function(){ alert(this.name); } } //测试 function test(){ var people=new hello(); people.say(); alert(peopl