面向对象小结

面向对象之构造函数

结构:

    function 构造函数() {
        this.属性 = valve
    }
    构造函数.prototype.方法 = function() {

    }
    var 对象1 = new 构造函数();
        对象1.方法();


 eg :
        function Person() {
            this.name = 'bob';
        }
        Person.prototype.sayName = function() {
            alert(this.name)
        }

        var p1 = new Person();
        alert(p1.name);  // bob
        p1.sayName();  //bob

tips : 当`new`去调用一个函数,函数中的`this`就是`new`创建出来的对象,而且函数的返回值就是`this`,也就是对象(隐式返回)

如何改写面向对象的选项卡

原则:
先写出普通的方法,再改成面向对象的写法。
1、普通的方法
(1)尽量不要出现函数嵌套函数
(2)可以有全局变量
(3)把onload中不是赋值的语句放到单独函数中。
2、改成面向对象
(1)全局变量就是属性
(2)函数就是方法
(3)onload中创建对象
(4)改this指向问题,尽量让this指向对象

eg:
<body>
    <input type="button" value="选项1" class="active">
    <input type="button" value="选项2">
    <input type="button" value="选项3">
    <div class="box1" style="display:block">内容一</div>
    <div class="box2">内容二</div>
    <div class="box3">内容三</div>
</body>
/*面向对象写法*/
window.onload = function(){
        var t1=new Tab('tab1');
        t1.init();
        t1.autoPlay(2000);  

        var t2=new Tab('tab2'); //新弄的一个
        t2.init();
        t2.autoPlay(1000); 
    }
    function Tab(id) {
        this.oTaba=document.getElementById(id);
        this.aInp=this.oTaba.getElementsByTagName('input');
        this.aDiv=this.oTaba.getElementsByTagName('div');
        this.iNow=0;
    }
    Tab.prototype.init = function() {
        var This=this;
        for (var i = 0; i < this.aInp.length; i++) {
            this.aInp[i].index=i;
            this.aInp[i].onclick=function() {
                console.log(this)
                This.change(this);
            };
        };
    }
    Tab.prototype.change = function(obj) {
        for (var i = 0; i < this.aInp.length; i++) {
            this.aInp[i].className='';
            this.aDiv[i].className='';
        };
        obj.className='active';
        this.aDiv[obj.index].className='active';
    };

    Tab.prototype.autoPlay = function (time){
        var This=this;
        setInterval(function(){
            This.iNow++;
            if (This.iNow == This.aInp.length) {
                This.iNow=0;
            };
            for (var i = 0; i < This.aInp.length; i++) {
                This.aInp[i].className='';
                This.aDiv[i].className='';
            };
            This.aInp[This.iNow].className='active';
            This.aDiv[This.iNow].className='active';
        },time)
    } 

包装对象

1、系统对象也是基于原型prototype的程序
2、基本类型都有自己对应的包装对象 : String 、 Number、 Boolean(除了null 和 undefined)

var str = 'abc';
str.charAt(0);  //基本类型会找到对应的包装对象,包装对象把所有的属性和方法给了基本类型,然后包装对象消失

原型链

1 、实例对象与原型之间的链接,叫做原型链。最外层是Object.prototype
2、proto(原型链,隐式连接) ,先找普通方法,再找原型。最后找最外层
3、Object对象类型时原型链的最外层

面向对象的一些属性和方法

1、hasOwnPrototype(); 看是不是自身下面的属性和方法,不会查找原型下面的属性和方法
2、constructor : 查看对象的构造函数。

        function Person() {

        }
        Person.prototype.name = 'Bob';
        Person.prototype.age = 100;
        Person.prototype.constructor = Person  //自动生成,不要手动添加
        var p1 = new Person();
        alert( p1.constructor )  //function Person() {}

/** tips :写成对象字面量时 指向问题  **/
        function Person() {

        }
        Person.prototype = {
            name : 'Bob',
            age : 100
        }
        var p1 = new Person();
        alert( p1.constructor )  //function Object() {[native code]} 

解决办法 :手动修改指向
        Person.prototype = {
            constructor  : Person,
            name : 'Bob',
            age : 100
        }

3、for in
找不到系统自带的属性,比如constructor,自己写constructor也找不到

4、instanceof : 运算符,对象与构造函数在原型链上是否有联系,任何对象instanceof Object 都是true

5、toString : Object上的方法,也可用作类型的判断(最靠谱);系统对象下面都是自带的,写在构造函数prototype下的,自己写的都是通过原型链找Object下面的(Object.prototype)

var arr = [];
alert( Object.prototype.toString.call(arr) ) // '[object Array]'

继承

概念 : 在原有对象的基础上,略作修改,得到一个新的对象,并且不影响原有对象

常用的继承方式:

属性的继承 : call
方法的继承 :for in (浅复制与深复制)

function Person (name,age) {
        this.name = name;
        this.age = age;
    }
    Person.prototype.sayName = function () {
        alert(this.name)
    }
    Person.prototype.sayAge = function () {
        alert(this.age)
    }
    function Start (name, age, job) {
        Person.call(this,name,age); //属性继承
        this.job = job;
    }
    extend(Start.prototype,Person.prototype); //方法继承,浅复制
    Start.prototype.sayJob = function () {
        alert(this.job);
    }

    function extend (obj1,obj2) {
        for (var attr in obj2) {
            obj1[attr] = obj2[attr]
        }
    }
    var s1 = new Start('黄晓明',20,'stat');
    s1.sayAge();
    s1.sayJob();

    var p1 = new Person('小球',100);
    alert(p1.name);

继承的其他方式

1、类式继承 : 利用构造函数继承的方式
类 : js是没用类概念的,把构造函数看做是类

子构造函数.prototype = new 父构造函数  //继承的属性和方法

存在的问题 : ,
(1)constructor的指向问题 (需手动指向)
(2)实例1 的属性方法修改会影响 实例2 (想想原型链的查找 , 属性和方法分开继承)

function Person1(name) {
        this.name = name;
        this.job = 'worker';
    }
    Person1.prototype.sayName = function() {
        alert(this.name);
    }
    Person1.prototype.sayJob = function() {
        alert(this.job);
    }
    function Person2(name,age) {
        Person1.call(this,name,age); //继承属性
        this.age = age;
        this.job = 'student';
    }

    /** 下面四行重点,前三行继承方法,第四行解决指向问题 **/
    var F = function(){};
    F.prototype = Person1.prototype;
    Person2.prototype = new F();
    Person2.prototype.constructor = Person2;

    Person2.prototype.sayAge = function() {
        alert(this.age);
    }

    var p1 = new Person2('小强','255');
    alert(p1.name);
    p1.sayName();
    p1.sayAge();

2、原型继承 : 借助原型来实现对象继承对象

function Person() {
            this.name = 'bob';
            this.job = 'worker';
        }
        Person.prototype.sayName = function() {
            alert(this.name);
        }
        Person.prototype.sayJob = function() {
            alert(this.job);
        }

        var p2 = cloneObj(Person);
        p2.name = 'xiaohua';
        p2.age = 289;
        p2.sayName();
        function cloneObj(obj) {
            var F = function(){};
            F.prototype = obj.prototype;

            return new F(); 
        }

组件开发

组件开发 : 多组对象,像兄弟之间的关系,代码复用(UI组件,功能组件)
默认参数 : 写在构造函数中,普通方法
配置参数 : 写在参数中

//组件开发弹出框
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style type="text/css">
    * {margin: 0;padding: 0}
    .loading1 {border: 1px solid #000;position: absolute;left: 0;top: 0;z-index: 10}
    .loading1 p {width: 100%;height: 40px;background: #0cf}
    .loading1 p .close {float: right;}
    #mark {width: 100%; height: 100%; position: absolute; left: 0; top: 0; background: rgba(0,0,0,.4);}
    </style>
    <script type="text/javascript">
    window.onload = function() {
        var aInp = document.getElementsByTagName('input');

        aInp[0].onclick = function() {
            var l1 = new Load();
            l1.init({
                iNow : 1,
                drag : true
            })
        }

        aInp[1].onclick = function() {
            var l2 = new Load();
            l2.init({
                iNow : 2,
                w : '100',
                h : '400',
                dir : 'right',
                title : '广告'
            });
        }

        aInp[2].onclick = function() {
            var l3 = new Load();
            l3.init({
                iNow : 3,
                title : '推广',
                mark : true
            })
        }

    }
    function Load() {
        this.obj = null;
        this.mark = null;
        this.disX = 0;
        this.disY = 0;
        this.settings = {
            w : '300',
            h : '300',
            dir : 'center',
            title : '登陆',
            mark : false,
            toDown : function(){},
            toMove : function(){},
            toUp : function(){}
        }
    }
    Load.prototype.json = {}; // 处理多次点击多次添加的问题
    Load.prototype.init = function(opt) {
        var This = this;
        extend(this.settings , opt);

        if (this.json[opt.iNow] == undefined) {
            this.json[opt.iNow] = true;
        }
        if (this.json[opt.iNow]) {
            this.cresteData();

            this.json[opt.iNow] = false;
        };

    }
    Load.prototype.cresteData = function() {

        this.obj = document.createElement('div');
        this.obj.className = 'loading1';
        this.obj.innerHTML = '<p><span>登陆</span><span class="close">X</span></p>';

        document.body.appendChild(this.obj);
        this.fnMark();
        this.setData();
        this.drag();
        this.fnClose();
    }

    Load.prototype.setData = function() {
        var oTitle = this.obj.getElementsByTagName('span')[0];
        this.obj.style.width = this.settings.w + 'px';
        this.obj.style.height = this.settings.h + 'px';
        oTitle.innerHTML = this.settings.title;
        if ( this.settings.dir == 'center' ) {
            this.obj.style.left = ( viewWidth() - this.obj.offsetWidth )/2 + 'px';
            this.obj.style.top = ( viewHeight() - this.obj.offsetHeight )/2 + 'px';
        }else if ( this.settings.dir == 'right' ) {
            this.obj.style.left = ( viewWidth() - this.obj.offsetWidth ) + 'px';
            this.obj.style.top = ( viewHeight() - this.obj.offsetHeight ) + 'px';
        }
    }

    Load.prototype.fnClose = function() {
        var This = this;
        var oClose = this.obj.getElementsByTagName('span')[1];
        oClose.onclick = function (){
            document.body.removeChild( This.obj );
            This.json[This.settings.iNow] = true;
            console.log( This.settings )
            if ( This.settings.mark ) {
                document.body.removeChild( This.mark );
            };
        }
    }

    Load.prototype.fnMark = function() {
        if (this.settings.mark == true ) {
            this.mark = document.createElement('div');
            this.mark.id = 'mark';
            document.body.appendChild(this.mark)
        };
    }
    Load.prototype.drag = function (){
        var This = this;
        if (this.settings.drag) {
            this.obj.onmousedown = function(ev) {
                var ev = ev || window.event;
                This.fnDown(ev);
                // This.settings.toDown();
                return false;

            }
        };


    }
    Load.prototype.fnDown = function(ev) {
        var This=this;
        this.disX = ev.clientX - this.obj.offsetLeft;
        this.disY = ev.clientY - this.obj.offsetTop;
        document.onmousemove = function(ev) {
            var ev = ev || window.event;
            This.fnMove(ev);
            // This.default.toMove();
        }
        document.onmouseup = function(ev) {
            var ev = ev || window.event;
            This.fnUp();
            // This.default.toUp();

        }
    }
    Load.prototype.fnMove = function(ev) {
        var iLeft = ev.clientX - this.disX;
        var iTop = ev.clientY - this.disY;
        if (iLeft < 0) {
            iLeft = 0;
        }else if (iLeft > viewWidth()-this.obj.offsetWidth) {
            iLeft = viewWidth()-this.obj.offsetWidth;
        }
        this.obj.style.left = iLeft + 'px';
        this.obj.style.top = iTop + 'px';
    }
    Load.prototype.fnUp = function() {
        document.onmousemove = null;
        document.onmouseup = null;
    }
    function extend (obj1,obj2) {
        for(var attr in obj2){
            obj1[attr] = obj2[attr]
        }
    }
    function viewWidth() {
        return document.documentElement.clientWidth;
    }
    function viewHeight() {
        return document.documentElement.clientHeight;

    }
    </script>
</head>
<body>
    <input type="button" value="1" />
    <input type="button" value="2" />
    <input type="button" value="3" />
    <!-- <div class="loading1">
        <p><span>登陆</span><span class="close">X</span></p>
    </div> -->
    <!-- <div id="mark"></div> -->
</body>
</html>
//组件开发选项卡
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style type="text/css">
    #tab1,#tab2,#tab3 {width: 300px;height: 300px;}
    #tab1 div,#tab2 div,#tab3 div {width: 300px;height: 200px;border: 1px solid #000;display: none;}
    input {width: 60px;height: 30px;}
    .active {background: red}

    </style>
    <script type="text/javascript">
    window.onload = function() {
        var t1 = new Tab();
        t1.init({
            id : 'tab1',
            events : 'onclick'
        });

        var t2 = new Tab();
        t2.init({
            id : 'tab2',
            events : 'onmouseover'
        })
        t2.delay();

        var t3 = new Tab();
        t3.init({
            id : 'tab3',
            events : 'onmouseover'
        });
        t3.setIndex(1);

    }
    function Tab() {
        this.obj = null;
        this.aBtn = null;
        this.aBox = null;
        this.timer = null;
        this.settings = {
            events : 'onclick'
        }
    }
    Tab.prototype.init = function(opt) {
        extend(this.settings,opt)
        this.obj = document.getElementById(opt['id']);
        this.aBtn = this.obj.getElementsByTagName('input');
        this.aBox = this.obj.getElementsByTagName('div');
        this.change();

    }
    Tab.prototype.change = function() {
        var This = this;
        for (var i = 0; i < This.aBtn.length; i++) {
            This.aBtn[i].index = i;
            This.aBtn[i][This.settings.events] = function() {
                var _this = This;
                for (var i = 0; i < _this.aBtn.length; i++) {
                    _this.aBtn[i].className = '';
                    _this.aBox[i].style.display = 'none';
                };
                this.className = 'active';
                _this.aBox[ this.index ].style.display = 'block';

            }
        };
    }
    Tab.prototype.delay = function() {
        var This = this;
        for (var i = 0; i < this.aBtn.length; i++) {
            this.aBtn[i].index = i;

            this.aBtn[i].onmouseout = function() {
                clearTimeout(This.timer);
            }

            this.aBtn[i][this.settings.events] = function() {
                var _index = this.index;

                This.timer = setTimeout(function(){
                        toDelay(_index)
                },200)

            }
        }
        function toDelay(index) {
            for (var i = 0; i < This.aBtn.length; i++) {
                This.aBtn[i].className = '';
                This.aBox[i].style.display = 'none';
            };
            This.aBtn[index].className = 'active';
            This.aBox[index ].style.display = 'block';
        }

    }
    Tab.prototype.setIndex = function(index) {
        for (var i = 0; i < this.aBtn.length; i++) {
            this.aBtn[i].className = '';
            this.aBox[i].style.display = 'none'
        };
        this.aBtn[index].className = 'active';
        this.aBox[index].style.display = 'block'
    }
    function extend(obj1,obj2) {
        for(var attr in obj2) {
            obj1[attr] = obj2[attr]
        }
    }
    </script>
</head>
<body>
    <div id="tab1">
        <input type="button" value="1" class="active" />
        <input type="button" value="2" />
        <input type="button" value="3" />
        <div style="display: block;">111111111</div>
        <div>22222222</div>
        <div>33333333</div>
    </div>
    <div id="tab2">
        <input type="button" value="1" class="active" />
        <input type="button" value="2" />
        <input type="button" value="3" />
        <div style="display: block;">111111111</div>
        <div>22222222</div>
        <div>33333333</div>
    </div>
    <div id="tab3">
        <input type="button" value="1" class="active" />
        <input type="button" value="2" />
        <input type="button" value="3" />
        <div style="display: block;">111111111</div>
        <div>22222222</div>
        <div>33333333</div>
    </div>
</body>
</html>

自定义事件 :

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script type="text/javascript">
    window.onload = function () {
        var oDiv = document.getElementById('div1');
        var oSpan = document.getElementById('span1');

        bindEvent(oDiv,'click',function(){
            alert(1)
        });

        bindEvent(oDiv,'click',function(){
            alert(2)
        });

        bindEvent(oSpan,'show',function(){
            alert(3)
        });

        bindEvent(oSpan,'show',function(){
            alert(4)
        });

        bindEvent(oSpan,'hide',function(){
            oSpan.style.background = 'red';
        });

        fireEvenet(oSpan,'hide')
        function bindEvent(obj,events,fn) {  //不完善,比如this指向
            // obj :图书馆的楼层
            // events :图书的分类(书架)
            // fn :一本书

            obj.listener = obj.listener || {};
            obj.listener[events] = obj.listener[events] || [];
            obj.listener[events].push(fn);

            if (obj.addEventListener) {
                obj.addEventListener(events,fn,false)
            }else{
                obj.attachEvent('on'+events,fn)
            }



        }

        function fireEvenet(obj,events) { //主动触发函数
            for (var i = 0; i < obj.listener[events].length; i++) {
                console.log(obj.listener[events])
                obj.listener[events][i]();
            };
        }
    }
    </script>
</head>
<body>
    <div id="div1">div</div>
    <span id="span1">span</span>
</body>
</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值