• JavaScript基础13——面向对象


    什么是面向对象?

    面向对象(Object Oriented,OO)是软件开发方法。面向对象的概念和应用已超越了程序设计和软件开发,扩展到如数据库系统,交互式界面,应用结构,应用平台,分布式系统,网络管理结构,CAD技术,人工智能等领域。面向对象是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后到产物,是一种高级的编程思想。
     
        面向对象就是一种新的编程模式。

    面向对象的特点

        封装:不考虑内部实现,只考虑功能实现
     
        继承:从已有对象上,继承出新对象
        
        多态:多种形态,一个功能的不同的应用场景

    对象的组成

        方法(有归属)----函数(自由的)
     
        属性(有归属)----变量(自由的)

    OOA和OOD

    OOA面向对象分析:
    面向对象分析:将大问题拆分成小问题,并试图用分工协作来完成的思维方式。
    OOD面向对象设计:
            1.分析模块后,确定职责
                大哥招小弟--端茶倒水,点烟捶背捏脚
     
            2.确定耦合关系
                确定通信关系,如何交流,暗号
                弊端:当耦合达到一定程度时,如果换了一个助理,需要重新耦合,资源消耗太大
               高内聚低耦合
     
            3.为OOP做准备
     
            分析角色特性:
                 我当老师----技术过硬
                       ----讲课技能(口才)
     
                 我当销售----沟通技巧(口才)
                
                找到角色共同特性----继承
    大量信息的处理和加工困难,打包之后,将内容包含在其中。信息传递速度更快,效率更高
            
        面向对象和面向过程的区别
            面向对象--先实现功能,再运行。分工协作,同时发生,解决问题。
            面向过程--一边实现,一边运行。效率低下。
        
        面向对象并不是程序员发明的。在程序中我们叫面向对象(OO),在生活中叫分工协作。

    构造函数

        function CreatPeople(name,age,like){
                this.name = name;
                this.age = age;
                this.like = like;
                this.show = function(){
                    alert("我叫"+this.name+",今年"+this.age+"岁,喜欢"+this.like);
                }
            }
            var obj = new CreatPeople("ABC",20,"PHP");
            var obj2 = new CreatPeople("QWE",32,"Python");
            obj.show();
            obj2.show();

    构造函数和对象的关系

        面向对象----对一个对象进行编程
        构造函数----提供一个对象供你编程
     
        通过构造函数,实现面向对象编程

    使用Json创建对象

        var obj = {
            name:"admin",
            age:23,
            like:"LOL",
            show:function(){
                alert("我叫"+this.name+",今年"+this.age+"岁,喜欢"+this.like)
            }
        }
        obj.show()

    使用构造函数创建对象

            function CreatPeople(name,age,like){
                this.name = name;
                this.age = age;
                this.like = like;
                this.show = function(){
                    alert("我叫"+this.name+",今年"+this.age+"岁,喜欢"+this.like);
                }
            }
            var obj = new CreatPeople("ABC",20,"PHP");
            var obj2 = new CreatPeople("QWE",32,"Python");
            obj.show();
    
            obj2.show();

    原型的概念

        在对象中,两个新创建的函数,是不相等的:
        var obj1 = {
            fn:function(){
                alert(1);
            }
        }
        var obj2 = {
            fn:function(){
                alert(1);
            }
        }
        console.log(obj1.fn == obj2.fn);    //false
    
        在构造函数中,同样属于两个新创建的函数,也是不相等的
        function Fn(name){
            this.name = name;
            this.show = function(){
                alert(this.name);
            }
        }
        var obj1 = new Fn("AAA");
        var obj2 = new Fn("BBB");
        console.log(obj1.show==obj2.show);        //false
        
        此时可以看出构造函数的多次创建会产生多个同名函数,造成冗余太多。
        
        利用原型prototype解决。
        function Fn(){}
        console.log(Fn.prototype);
        //constructor表示当前的函数属于谁
        //__proto__  ==  [[prototype]],书面用语,表示原型链
    
    
        var fn1 = new Object();
        var fn2 = new Object();
        Object.prototype.show = function(){
            alert(1);
        }
        console.log(fn1.show==fn2.show);     //ture
     
        此时,任何一个对象的原型上都有了show方法,由此得出,Object.prototype身上的添加的方法,相当于添加到了所有的Object身上。
        
        为了解决构造函数的冗余问题,我们将属性写在构造函数内,方法写在原型中。这是面向对象的编程格式之一。
        面向对象的编程格式之一:
            1.属性写在构造函数内;
            2.方法写在原型中
            3.构造函数中的this指向当前new出来的对象
           4.原型方法中的this指向当前原型所属的函数被new出来的对象
    在代码中再次看看区别
       // 1.创建对象:构造函数
            // function Fn(){
            //     this.xxx = xxxx;
            // }
            // var f = new Fn()
            
            // 模型,构造器
            function Fn(n){
                this.name = n;
                this.show();
            }
    
            Fn.prototype.show = function(){
                console.log(this.name)
            }
    
            var f1 = new Fn("admin");
            var f2 = new Fn("root");
    
    
            // new出来的实例
            console.log(f1);
            console.log(f2);
            console.log(f2 == f1);
            console.log(f2.__proto__ == f1.__proto__);
            console.log(f2.__proto__.show == f1.__proto__.show);
    
            f1.show();
            f2.show();
    
            // console.dir(Fn);
            // console.log(Fn.length)
            // console.log(Fn.name)
            // console.log(Fn.prototype)
            // console.log(f1.__proto__)
            // console.log(f1.__proto__ === Fn.prototype)
    
            // // 抽象
            // // 具象
            // f1.show();
            // f2.show();
            // console.log(f1.show == f2.show);
    
            console.log(f1.abc);
    
        
        // var arr1 = new Array("hello","world");
        // var arr2 = new Array("hello","html");
        // console.log(arr1);
        // console.log(arr2);
        // console.log(arr2 == arr1);
        // console.log(arr1.length);
        // console.log(arr2.length);
    
        // arr1.push("hello");
        // arr2.push("hello");
        
        // console.log(arr1.push == arr2.push);
        
        // Array.prototype.hahaha = function(){}
        // var arr = new Array();
        // arr.norepeat()
    
        // 为什么要相等?节省内存,减少方法的冗余
        // 怎么做?写成公共方法
        // 怎么实现?
        // ↓↓↓↓↓↓↓↓↓
        // __proto__:原型链(隐示原型),作用:与自身类型的父级建立连接
        // prototype:原型对象(显示原型),只有函数(除了箭头函数)才有,作用:为了给自身被new之后创建出来的实例做父级使用
    
        // 此属性对于函数自身来说,没有用
        // 但是这个属性是给函数被new执行创建出的实例,当爸的
    
        // new的原理:
            // 1.自动创建一个新对象
            // 2.改变了函数内部的this,为第一步的新对象
            // 3.将第一步创建的新对象的父级,改成new执行函数的prototype
            // 4.检测函数是否主动返回对象,没有,就返回第一步创建的新对象
    
        // 对象读取属性或方法的原则:
            // 就近原则:当对象查找自身的属性或方法时,如果自身有,直接使用;如果自身没有,顺着__proto__向上找父级,找到了就使用,没找到,继续向上;直到顶部,还没找到,就抛出undefined;在这个过程中,只要找到了,就停止向上查找。
            
        // 构造函数身上的原型对象身上的方法中的this,依然指向将来构造函数被new出来的实例

     面向对象案例——烟火

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset = "utf-8">
            <title></title>
            <style>
                .box { 800px;height: 600px;background-color: black;margin: 0 auto;position: relative;}
                .fire1 { 15px;height: 15px;border-radius: 50%;position: absolute;bottom: 0;}
                .fire2 { 10px;height: 10px;border-radius: 50%;position: absolute;}
            </style>
        </head>
        <body>
            <div class="box"></div>
        </body>
        <script>
            
            function Fire(obj){
                this.x = obj.x;
                this.y = obj.y;
                this.cont = obj.parent;
                this.onoff = obj.onoff;
                this.start();
            }
    
            Fire.prototype.start = function(){
                // 1.创建烟花给样式
                this.div = document.createElement("div");
                this.div.className = "fire1";
                this.div.style.background = randomColor();
                this.div.style.left = this.x + "px";
                this.cont.appendChild(this.div);
                // 开始运动this.transition();
                this.transition();
            }
    
            Fire.prototype.transition = function(){
                move(this.div,{top:this.y},()=>{
                    // 运动,结束后删除
                    this.div.remove();
                    // 3创建小烟花this.boom();
                    this.onoff = this.onoff == 1 ? this.boom1() : this.boom2();
                    //选择烟花样式
                })
            }
    
            Fire.prototype.boom1 = function(){
                // 4.小烟花运动,消失
                var num = random(2,3);
                for(var i = 0;i < num;i++){
                    let star = document.createElement("div");
                    star.className = "fire2";
                    star.style.background = randomColor();
                    star.style.left = this.x + "px";
                    star.style.top = this.y + "px";
                    this.cont.appendChild(star);
                    var l = random(0,this.cont.offsetWidth-star.offsetWidth);
                    var t = random(0,this.cont.offsetHeight-star.offsetHeight);
                    move(star,{left:l,top:t},function(){
                        star.remove();
                    })
                }
            }
            Fire.prototype.boom2 = function(){
                // 4.小烟花运动,消失
                var num = random(20,35);
                var r = random(100,200);
                for(var i = 0;i < num;i++){
                    let star = document.createElement("div");
                    star.className = "fire2";
                    star.style.background = randomColor();
                    star.style.left = this.x + "px";
                    star.style.top = this.y + "px";
                    this.cont.appendChild(star);
                    var l = parseInt(Math.cos(Math.PI/180*(360/num*i))*r)+this.x;
                    var t = parseInt(Math.sin(Math.PI/180*(360/num*i))*r)+this.y;
                    move(star,{left:l,top:t},function(){
                        star.remove();
                    })
                }
            }
    
    
    
    
            var obox = document.querySelector(".box");
            addEvent(obox,"mousemove",function(eve){
                var e = eve || window.event;
                new Fire({
                    x:e.offsetX,
                    y:e.offsetY,
                    parent:this,
                    onoff:1
                });
            })
    
            addEvent(obox,"contextmenu",function(eve){
                var e = eve || window.event;
                e.preventDefault();
                new Fire({
                    x:e.offsetX,
                    y:e.offsetY,
                    parent:this,
                    onoff:0
                });
            })
            // 运动
            function move(ele,obj,fn){
                clearInterval(ele.t);
                ele.t = setInterval(() => {
                var onoff = true;
                for(var i in obj){
                    var pos = parseInt(getComputedStyle(ele,false)[i]);
                    var speed = (obj[i]-pos)/10;
                    speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
                    if(pos != obj[i]){
                        onoff = false;
                    }
                    ele.style[i] = pos + speed + "px";
                    if(onoff == true){
                        clearInterval(ele.t);
                        fn && fn();
                    }
                }    
                }, 30);
            }
    
            // 范围随机数
            function random(max,min){
                return Math.round(Math.random()*(max-min)+min);
            }
            // 随机颜色
            function randomColor(){
                return "rgb("+random(0,255)+","+random(0,255)+","+random(0,255)+")";
            }
            // 监听式绑定:
            function addEvent(ele,eve,cb){
                if(ele.addEventListener){
                    ele.addEventListener(eve,cb);
                }else if(ele.attachEvent){
                    ele.attachEvent("on"+eve,cb);           //ie
                }else{
                    ele["on"+eve] = cb;
                }
            }
    
          
        </script>
    </html>
     
     
     
     
     
  • 相关阅读:
    bootstrap的portlet组件框框的应用 (点击可伸缩)
    jQuery.trim() 函数及trim()用法详解
    针对谷歌浏览器Chrome的CSS hack
    CSS-如何禁用a标签
    textarea中文本前总是空2格,写入数据库也是
    JNI编程实现(Windows)
    JNI编程实现(Linux)
    FastDFS安装步骤
    iOS离屏渲染之优化分析
    Nginx入门案例(Mac版)
  • 原文地址:https://www.cnblogs.com/wuziqiang/p/12077176.html
Copyright © 2020-2023  润新知