面向對象小結

面向對象之構造函數

結構:

    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].οnclick=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>
發佈了61 篇原創文章 · 獲贊 2 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章