JS面向对象1

什么是面向对象编程

  • 用对象的思想去写代码,就是面向对象编程

    • 历程式写法

    • 面向对象写法

  • 我们一向都在运用对象

    • 数组Array 时刻Date

面向对象编程(OOP)的特征

  • 笼统:捉住核心题目

  • 封装:只能经由历程对象来访问要领

  • 继承:从已有对象上继承出新的对象

  • 多态:多对象的差别形状

对象的构成

  • 要领(行动、操纵) —— 对象下面的函数:历程、动态的

  • 属性 —— 对象下面的变量:状况、静态的

竖立第一个面向对象递次

//var obj = {};
var obj = new Object(); //竖立了一个空的对象
obj.name = '小明'; //属性
obj.showName = function(){ //要领
    alert(this.name);
}
obj.showName();
  • 为对象增加属性和要领

    • Object对象

    • this指向

    • 竖立两个对象:反复代码过量

//var obj = {};
var obj = new Object(); //竖立了一个空的对象
obj.name = '小明'; //属性
obj.showName = function(){ //要领
    alert(this.name);
}
obj.showName();
var obj2 = new Object(); 
obj2.name = '小强';
obj.showName = function(){
    alert(this.name);
}
obj2.showName();

工场体式格局

面向对象中的封装函数

//工场体式格局:封装函数
function createPerson(name){
    //1. 质料
    var obj = new Object();  
    //2. 加工
    obj.name = name;
    obj.showName = function(){
        alert(this.name);
    };   
    //3. 出厂
    return obj;
}
var p1 = createPerson('小明');
p1.showName();
var p2 = createPerson('小强');
p2.showName();

改成与体系对象相似的写法
1、首字母大写
2、New关键字提取
3、this指向为新竖立的对象

/* 当new去挪用一个函数:这个时刻函数中的this就是竖立出来的对象,而且函数的返回值直接就是this啦。(这叫做隐式返回) */
// new背面挪用的函数:组织函数
function CreatePerson(name){
    this.name = name;
    this.showName = function(){
        alert(this.name);
    };
    // return obj; 隐式返回,所以这一行不必写了
}

var p1 = new CreatePerson('小明');
p1.showName();
var p2 = new CreatePerson('小强');
p2.showName();

组织函数
用来竖立对象的函数,叫做组织函数
存在的题目
1、对象的援用
2.糟蹋内存

/* 当new去挪用一个函数:这个时刻函数中的this就是竖立出来的对象,而且函数的返回值直接就是this啦。(这叫做隐式返回) */

// new背面挪用的函数:组织函数
function CreatePerson(name){
    this.name = name;
    this.showName = function(){
        alert(this.name);
    };
    // return obj; 隐式返回,所以这一行不必写了
}
var p1 = new CreatePerson('小明');
p1.showName();
var p2 = new CreatePerson('小强');
p2.showName();

//alert(p1.showName == p2.showName); //false
/*
    var a = [1, 2, 3];
    var b = [1, 2, 3];

    alert(a == b); //false;
*/

/*
    var a = 5;
    var b = a;
    b += a;
    alert(b); //8
    alert(a); //5 基础范例:赋值的时刻只是值的复制
*/

/*
    var a = [1, 2, 3]; 
    var b = a; 
    b.push(4);
    alert(b); //[1, 2, 3, 4]
    alert(a); //[1, 2, 3, 4] 对象范例:赋值不仅是值的复制,而且也是援用的通报
*/

/*
    var a = [1, 2, 3];
    var b = a;
    b = [1, 2, 3, 4];
    alert(b); //[1, 2, 3, 4]
    alert(a); //[1, 2, 3] 只需赋值就会在内存中从新天生,所以a,b互补影响
*/

/*
    var a = 5;
    var b = 5;
    alert(a == b); //true 基础范例的比较:只需值雷同就可以
*/

/*
    var a = [1, 2, 3];
    var b = [1, 2, 3];
    alert(a == b); //false 对象范例:值和援用都雷同才行
*/

/*
    var a = [1, 2, 3];
    var b = a;
    alert(a == b); //true
*/

原型 —— prototype

观点
去改写对象下面公用的要领或许属性,让公用的要领或许属性在内存中仅存在一份(优点:进步机能)

进修原型

  1. 类比:原型就是CSS中的class(一般要领就是CSS中的style)

  2. 一般要领的优先级比原型要高

  3. 原型可以复用,一般要领不可以复用

var arr = []; 
arr.number = 10;
Array.prototype.number = 20;
alert(arr.number); //10 一般要领的优先级高于原型
//原型:prototype:要写在组织函数下面
var arr = [1, 2, 3, 4, 5];
var arr2 = [2, 2, 2, 2, 2];
Array.prototype.sum = function(){
    var result = 0;
    for(var i=0; i<this.length; i++){
        result += this[i];
    }
    return result;
}

/*
arr.sum = function(){
    var result = 0;
    for(var i=0; i<this.length; i++){
        result += this[i];
    }
    return result;
}

alert(arr.sum()); //15
*/
alert(arr.sum());
alert(arr2.sum());

经由历程原型改写工场体式格局准绳:

  1. 雷同的属性和要领可以加在原型上

  2. 夹杂的编程情势

function CreatePerson(name){
    this.name = name; //变化的,不能公用的属性不能写在原型上
}
CreatePerson.prototype.showName = function(){
    alert(this.name);
}   

var p1 = new CreatePerson('小明');
var p2 = new CreatePerson('小强');

alert(p1.showName == p2.showName); //true

夹杂的编程情势

//面向对象的写法
function 组织函数(){
    this.属性
}
组织函数.原型.要领 = function(){};

//面向对象的运用
var 对象1 = new 组织函数();
对象1.要领();

总结面向对象写法:组织函数加属性,原型加要领

面向对象的选项卡

准绳
先写出一般的写法,然后改成面向对象写法

  • 一般要领变型

    • 只管不要涌现函数嵌套函数

    • 可以有全局变量

    • 把onload中不是赋值的语句放到零丁的函数中

  • 改成面向对象

    • 全局变量就是属性

    • 函数就是要领

    • onload中竖立对象

    • 改this指向题目,要只管让面向对象中的this指向对象

1、先写出一般要领

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>面向对象的选项卡</title>
    <style>
        #div1 div { width: 200px; height: 200px; border: 1px solid #000; display: none; }
        .active { background: red; }
    </style>
    <script>
        window.onload = function(){
            var oParent = document.getElementById('div1');
            var aInput = oParent.getElementsByTagName('input');
            var aDiv = oParent.getElementsByTagName('div');

            for(var i=0; i<aInput.length; i++){
                aInput[i].index = i;
                aInput[i].onclick = function(){
                    for(var i=0; i<aInput.length; i++){
                        aInput[i].className = '';
                        aDiv[i].style.display = 'none';
                    }
                    this.className = 'active';
                    aDiv[this.index].style.display = 'block';
                }
            }
        }
    </script>
</head>
<body>
    <div id="div1">
        <input type="button" value="1" class="active">
        <input type="button" value="2">
        <input type="button" value="3">
        <div style="display: block">11111</div>
        <div>22222</div>
        <div>33333</div>
    </div>
</body>
</html>

2、一般要领变型

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>面向对象的选项卡</title>
    <style>
        #div1 div { width: 200px; height: 200px; border: 1px solid #000; display: none; }
        .active { background: red; }
    </style>
    <script>

        var oParent = null;
        var aInput = null;
        var aDiv = null;

        window.onload = function(){
            oParent = document.getElementById('div1');
            aInput = oParent.getElementsByTagName('input');
            aDiv = oParent.getElementsByTagName('div');

            init();
            
        };

        function init(){ //初始化的函数要领
            for(var i=0; i<aInput.length; i++){
                aInput[i].index = i;
                aInput[i].onclick = change;
            }
        }

        function change(){
            for(var i=0; i<aInput.length; i++){
                aInput[i].className = '';
                aDiv[i].style.display = 'none';
            }
            this.className = 'active';
            aDiv[this.index].style.display = 'block';
        }

        /*
        - 一般要领变型
            - 只管不要涌现函数嵌套函数
            - 可以有全局变量
            - 把onload中不是赋值的语句放到零丁的函数中
        */
    </script>
</head>
<body>
    <div id="div1">
        <input type="button" value="1" class="active">
        <input type="button" value="2">
        <input type="button" value="3">
        <div style="display: block">11111</div>
        <div>22222</div>
        <div>33333</div>
    </div>
</body>
</html>

关于this的指向

oDiv.onclick = function(){
    this: oDiv
};

---

oDiv.onclick = show;
function show(){
    this: oDiv
}

---

oDiv.onclick = function(){
    show();
};
function show(){
    this: window
}

改写成面向对象

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>面向对象bianxie</title>
    <style>
        #div1 div { width: 200px; height: 200px; border: 1px solid #000; display: none; }
        .active { background: red; }
    </style>
    <script>

        var oParent = null;
        var aInput = null;
        var aDiv = null;

        window.onload = function(){
            
            var t1 = new Tab();
            t1.init();
            
        };

        function Tab(){
            this.oParent = document.getElementById('div1');
            this.aInput = this.oParent.getElementsByTagName('input');
            this.aDiv = this.oParent.getElementsByTagName('div');
        }

        Tab.prototype.init = function(){
            var This = this;
            for(var i=0; i<this.aInput.length; i++){
                this.aInput[i].index = i;
                this.aInput[i].onclick = function(){
                    This.change(this);
                };
            }
        }

        Tab.prototype.change = function(obj){
            for(var i=0; i<this.aInput.length; i++){
                this.aInput[i].className = '';
                this.aDiv[i].style.display = 'none';
            }
            obj.className = 'active';
            this.aDiv[obj.index].style.display = 'block';
        }

        /*
        - 改成面向对象
            - 全局变量就是属性
            - 函数就是要领
            - onload中竖立对象
            - 改this指向题目:注重事宜或许是定时器内里的this。要只管坚持面向对象中的this指向对象
        */
    </script>
</head>
<body>
    <div id="div1">
        <input type="button" value="1" class="active">
        <input type="button" value="2">
        <input type="button" value="3">
        <div style="display: block">11111</div>
        <div>22222</div>
        <div>33333</div>
    </div>
</body>
</html>

面向对象的复用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>面向对象bianxie</title>
    <style>
        #div1 div, #div2 div { width: 200px; height: 200px; border: 1px solid #000; display: none; }
        .active { background: red; }
    </style>
    <script>

        var oParent = null;
        var aInput = null;
        var aDiv = null;

        window.onload = function(){
            
            var t1 = new Tab('div1');
            t1.init();

            var t2 = new Tab('div2');
            t2.init();
            t2.autoplay();
            
        };

        function Tab(id){
            this.oParent = document.getElementById(id);
            this.aInput = this.oParent.getElementsByTagName('input');
            this.aDiv = this.oParent.getElementsByTagName('div');
            this.iNow = 0;
        }

        Tab.prototype.init = function(){
            var This = this;
            for(var i=0; i<this.aInput.length; i++){
                this.aInput[i].index = i;
                this.aInput[i].onclick = function(){
                    This.change(this);
                };
            }
        }

        Tab.prototype.change = function(obj){
            for(var i=0; i<this.aInput.length; i++){
                this.aInput[i].className = '';
                this.aDiv[i].style.display = 'none';
            }
            obj.className = 'active';
            this.aDiv[obj.index].style.display = 'block';
        }
        Tab.prototype.autoplay = function(){
            var This = this;
            setInterval(function(){
                if(This.iNow == This.aInput.length - 1){
                    This.iNow = 0;
                } else {
                    This.iNow ++;
                }
                for(var i=0; i<This.aInput.length; i++){
                    This.aInput[i].className = '';
                    This.aDiv[i].style.display = 'none';
                }
                This.aInput[This.iNow].className = 'active';
                This.aDiv[This.iNow].style.display = 'block';
            }, 2000)
        }
    </script>
</head>
<body>
    <div id="div1">
        <input type="button" value="1" class="active">
        <input type="button" value="2">
        <input type="button" value="3">
        <div style="display: block">11111</div>
        <div>22222</div>
        <div>33333</div>
    </div>

    <div id="div2">
        <input type="button" value="1" class="active">
        <input type="button" value="2">
        <input type="button" value="3">
        <div style="display: block">11111</div>
        <div>22222</div>
        <div>33333</div>
    </div>
</body>
</html>

面向对象的拖拽

注重

  1. Event对象(event对象一定要写到事宜函数内里)

  2. 事宜函数中用来阻挠默许行动的return false也要写到事宜函数内里

!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>面向对象编写拖拽</title>
    <style>
        #div1 { width: 100px; height: 100px; background: red; position: absolute; }
    </style>
    <script>

    /* 一般拖拽
        window.onload = function(){
            var oDiv = document.getElementById('div1');
            var disX = 0;
            var disY = 0;

            oDiv.onmousedown = function(ev){
                var ev = ev || window.event;

                disX = ev.clientX - oDiv.offsetLeft;
                disY = ev.clientY - oDiv.offsetTop;

                document.onmousemove = function(ev){
                    var ev = ev || window.event;

                    oDiv.style.left = ev.clientX - disX + 'px';
                    oDiv.style.top = ev.clientY - disY + 'px';
                }

                document.onmouseup = function(){
                    document.onmousemove = null;
                    document.onmouseup = null;
                }

                return false;

            }
        }
    */

    /* 第一步:一般要领变型
    //先变型
        var oDiv = null;
        var disX = 0;
        var disY = 0;

        window.onload = function(){
            oDiv = document.getElementById('div1');
            init();         
        }

        function init(){
            oDiv.onmousedown = fnDown;
        }

        function fnDown(ev){
            var ev = ev || window.event;

                disX = ev.clientX - oDiv.offsetLeft;
                disY = ev.clientY - oDiv.offsetTop;

                document.onmousemove = fnMove;
                document.onmouseup = fnUp;

                return false;
        }

        function fnMove(ev){
            var ev = ev || window.event;

            oDiv.style.left = ev.clientX - disX + 'px';
            oDiv.style.top = ev.clientY - disY + 'px';
        }

        function fnUp(){
            document.onmousemove = null;
            document.onmouseup = null;
        }
        */

        //改成面向对象
        window.onload = function(){
            var d1 = new Drag('div1');
            d1.init();          
        }

        function Drag(id){
            this.oDiv = document.getElementById(id);
            this.disX = 0;
            this.dixY = 0;
        }

        Drag.prototype.init = function(){
            var This = this;
            this.oDiv.onmousedown = function(ev){
                var ev = ev || window.event;
                This.fnDown(ev);
                return false;
            };
        }

        Drag.prototype.fnDown = function(ev) {
            var ev = ev || window.event;
            var This = this;

                this.disX = ev.clientX - this.oDiv.offsetLeft;
                this.disY = ev.clientY - this.oDiv.offsetTop;

                document.onmousemove = function(ev){
                    var ev = ev || window.event;
                    This.fnMove(ev);
                };
                document.onmouseup = this.fnUp;         
        }

        Drag.prototype.fnMove = function(ev){
            this.oDiv.style.left = ev.clientX - this.disX + 'px';
            this.oDiv.style.top = ev.clientY - this.disY + 'px';
        }

        Drag.prototype.fnUp = function(){
            document.onmousemove = null;
            document.onmouseup = null;
        }
    </script>
</head>
<body>
    <div id="div1"></div>
</body>
</html>

本课演习

  1. 为数组对象增加乞降,最大值

  2. 为字符串对象增加推断是不是是末了一个字母

  3. 面向对象的选项卡

  4. 给选项卡增加一个自动播放的要领

  5. 恣意学过的结果改写成面向对象

  6. 面向对象的面试题

高等面向对象

包装对象

JS基于原型的递次
String Number Boolean

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style> 

    </style>
    <script>

    /*
        function Aaa(){
            this.name='小明';
        }

        Aaa.prototype.showName=function(){
            alert(this.name);
        }

        var a1 = new Aaa();
        a1.showName();

        var arr = new Array();
        arr.push();
        arr.sort();

        // 在js源码中:体系对象也是基于原型的递次

        function Array(){
            this.length = 0;
        }

        Array.prototype.push = function(){};
        Array.prototype.sort = function(){};
    */

    //只管不要去修改或增加体系对象下面的要领和属性
    var arr = [1, 2, 3];
    //Arr.prototype.push = function(){}; //加上这句话,就修改了源码中的push要领,那末背面那一句中的4、5、6就增加不进去了
    Array.prototype.push = function(){ //本身写一个数组的push要领
        //this : 1, 2, 3
        //arguments: 4, 5, 6

        for(var i=0; i<arguments.length; i++){
            this[this.length] = arguments[i];
        }

        return this.length;
    }
    arr.push(4, 5, 6);
    alert(arr);
    </script>
</head>
<body>
</body>
</html>

给基础范例增加要领

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style> 

    </style>
    <script>
    /*
        var str = 'hello';
        alert( typeof str); //string
        str.charAt(0); //字符串为何下面会有要领呢?
        str.indexOf('e');
    */

    //包装对象:基础范例都有本身对应的包装对象(String, Number, Boolean)(null和undefined没有包装对象)

    /*
    var str = new String('hello');
    alert(typeof str); //object
    alert(str.charAt(1)); //弹出e

    String.prototype.charAt = function(){}; //基础范例的要领都是放在它们的包装对象上
    */

    /*
    var str = 'hello'; //str是字符串
    str.charAt(0); //基础范例找到对应的包装对象范例,然后包装对象把一切的属性和要领给了基础范例,然后包装对象消逝
    */

    //给基础范例增加对象的时刻,就是把要领增加到基础范例对应的包装对象下面
    var str = 'hello';
    String.prototype.lastValue = function(){
        return this.charAt(this.length-1);
    };
    alert(str.lastValue()); //o
    
    var str1 = 'hello';
    str1.number = 10; //在str1的包装对象上竖立了一个number,然后包装对象就消逝了
    alert(str1.number); //undefined 再去挪用这句话的时刻,此时又从新竖立了一个对象,这个对象与适才谁人对象不是同一个    

    </script>
</head>
<body>
</body>
</html>

原型链

  • 实例对象与原型之间的衔接,叫做原型链

  • proto (隐式衔接)

  • Object对象范例是原型链的最外层

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>面向对象中的原型链</title>
    <style></style>
    <script>
    
        //原型链:实例对象与原型之间的衔接叫作原型链
        //_proto_ (隐式衔接)
        //原型链的最外层是Object.prototype

        function Aaa(){
            
        }

        Aaa.prototype.num = 10;

        var a1 = new Aaa();
        alert(a1.num); //10 a1如今它本身下面找,找不到这个num,然后又经由历程原型链到了Aaa.prototype,到它下面去找,终究找到了num

        function Bbb(){
            this.num = 20;
        }

        Bbb.prototype.num = 10;
        var b1 = new Bbb();
        alert(b1.num); //20 简朴来说,实例上的要领的优先级高于原型上的要领;本质上来说,是从b1下面找num直接就找到了,因而就不须要再进一步经由历程原型链去找到Bbb.prototype上的num了。

        function Ccc(){};
        var c1 = new Ccc();
        Object.prototype.num = 30; //弹出30 c1下找不到num;顺着原型链找到Ccc也找不到num,继承顺着原型链往上找,找到Object.prototype,找到了num
        alert(c1.num);
    </script>
</head>
<body>
</body>
</html>

面向对象的一些属性和要领

hasOwnProperty()看是不是是对象本身下面的属性

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>面向对象中的原型链</title>
    <style></style>
    <script>
        //hasOwnProperty: 看是不是是对象本身下面的属性

        var arr = [];
        arr.num = 10;
        Array.prototype.num2 = 20;

        alert(arr.hasOwnProperty('num')); //true
        alert(arr.hasOwnProperty('num2')); //false
        alert(arr.hasOwnProperty == Object.prototype.hasOwnProperty); //true hasOwnProperty实际上是Object.prototype下面的要领
    </script>
</head>
<body>
</body>
</html>

constructor检察对象的组织函数

  • 每一个原型都邑自动增加constructor属性

  • for in 的时刻,有些属性是找不到的

  • 防备修改constructor属性

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>面向对象中的原型链</title>
    <style></style>
    <script>
        //constructor: 检察对象的组织函数

        function Aaa(){

        }

        var a1 = new Aaa();

        alert(a1.constructor); //function Aaa

        var arr = [];
        alert(arr.constructor == Array); //true

        /*
        在写完一个组织函数以后
        function Aaa(){}
        递次会自动增加一句话:
        Aaa.prototype.constructor = Aaa; //每一个函数都邑有的,都是自动天生的
        这时刻new一个Aaa
        var a1 = new Aaa();
        alert(a1.constructor); //弹出Aaa
        假如手动写一句:
        Aaa.prototype.constructor = Array;
        那末再去弹a1.constructor的话,弹出的就是Array了。

        而hasOwnProperty这个属性是增加在Object.prototype下面的,所以每一个对象下面去查这个hasOwnProperty也都邑有。然则hasOwnProperty这个要领不是在详细对象下面的,而都是沿着原型链找到Object.prototype身上找到的。跟constructor是不一样的。
        */

        function Bbb(){

        }

        Bbb.prototype.name = '小明';
        Bbb.prototype.age = 20;

        var b1 = new Bbb();
        alert(b1.constructor); //function Bbb()

        //下面这类写法就无意识地转变了c1的constructor,由于json直接赋值给了Ccc.prototype,而不是向上面那段代码是增加操纵。那末底本体系自动天生的那句话Ccc.prototype.constructor = Ccc这句话就被掩盖掉了。然后经由历程c1.constructor去找的话,实在找的就是这个json所对应的constructor了。
        function Ccc(){

        }
        Ccc.prototype = {
            name: '小明',
            age: 20
        }
        var c1 = new Ccc();
        alert(c1.constructor); //function Object

        //为了防备上述题目,应当注重,用json简写的时刻,要把constructor修改过来,以下:

        function Ddd(){

        }
        Ddd.prototype = {
            constructor: Ddd, //经由历程这一句来修改一下
            name: '小明',
            age: 20
        }
        var d1 = new Ddd();
        alert(d1.constructor); //Ddd

    </script>
</head>
<body>
</body>
</html>

for in轮回,有些属性找不到

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>面向对象中的原型链</title>
    <style></style>
    <script>
        function Aaa(){

        }
        Aaa.prototype.name = 10;
        Aaa.prototype.constructor = Aaa;
        for (var attr in Aaa.prototype){
            alert(attr); //只能找到本身增加的,体系自动天生的比方constructor,for in轮回是找不到的
        }
    </script>
</head>
<body>
</body>
</html>

instanceof运算符

对象与组织函数在原型链上是不是有关联
可以用来作范例推断

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>instanceof()</title>
    <style></style>
    <script>
        // instanceof: 对象与组织函数在原型链上是不是有关联

        function Aaa(){

        }
        var a1 = new Aaa();
        alert(a1 instanceof Aaa); //true 看a1是不是与Aaa在同一个原型链上
        alert(a1 instanceof Array); //false
        alert(a1 instanceof Object); //true
    </script>
</head>
<body>
</body>
</html>

toString()

object上的要领

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>toString()</title>
    <style></style>
    <script>
        // toString(): 
        // 位置:体系对象下面都是自带的;本身写的对象都是经由历程原型链找Object下面的
        // 作用:把对象转成字符串

        var arr = [];
        alert(arr.toString); //找获得
        alert(arr.toString == Object.prototype.toString); //false 体系对象下面的toString不在Object原型上

        function Aaa(){

        }
        var a1 = new Aaa();
        alert(a1.toString); //找获得
        alert(a1.toString == Object.prototype.toString); //true 组织函数天生的对象的toString要领在Object原型上

        var arr = [1, 2, 3];
        alert(typeof arr.toString()); //string

        alert(arr.toString()); //"1, 2, 3"

        //由于晓得toString在哪儿了,所以可以手动修改toString要领
        Array.prototype.toString = function(){
            return this.join('+');
        }
        alert(arr.toString()); //"1+2+3"

        var num = 255;
        alert(num.toString(16)); //"ff" 将255转成16进制

        //运用toString举行范例推断(用constructor和instanceof也都可以举行范例推断)。引荐toString来推断比方数组的范例
        var arr = []
        var date = new Date;
        var json = {}
        var reg = new RegExp;
        var n = null;
        alert(Object.prototype.toString.call(arr)); //[object Array]
        alert(Object.prototype.toString.call(date)); //[object Date]
        alert(Object.prototype.toString.call(json)); //[object Object]
        alert(Object.prototype.toString.call(reg)); //[object RegExp]
        alert(Object.prototype.toString.call(n)); //[object Null]
        //推断范例时直接举行比较就可以了,比方推断arr是不是是数组:
        alert(Object.prototype.toString.call(arr) == '[object Array]'); //true

        //举例说明用instanceof和constructor来推断数组失效,然则toString依旧有用的例子
        window.onload = function(){
            var oF = document.createElement('iframe');
            document.body.appendChild(oF);
            var ifArray = window.frames[0].Array; //ifArray就是iframe内里的数组
            var arr = new ifArray(); //ifArray就是iframe内里的数组 这时刻跨页面了

            alert(arr.constructor == Array); //false constructor推断iframe下面的数组失效
            alert(arr instanceof Array); //false 推断失效
            alert(Object.prototype.toString.call(arr) == '[object Array]'); //true 推断依旧有用
        }
    </script>
</head>
<body>
</body>
</html>

对象的继承

什么是继承

  • 在原有对象的基础上,略作修改,获得一个新的对象

  • 不影响原有对象的功用

怎样增加继承

  • 属性:call

  • 要领:for in

  • 例子:继承的拖拽

!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>继承</title>
    <style></style>
    <script>
        // 继承:子类不影响父类;子类可以继承父类的一些功用(完成代码复用)

        function CreatePerson(name, sex){ //父类
            this.name = name;
            this.sex = sex;
        }
        CreatePerson.prototype.showName = function(){
            alert(this.name);
        }

        var p1 = new CreatePerson('小明', '男');
        p1.showName();

        //属性的继承:挪用父类的组织函数 用call改this指向
        //要领的继承:用for in轮回

        function CreateStar(name, sex, job){ //子类
            // this.name = name;
            // this.sex = sex;

            CreatePerson.call(this, name, sex); //挪用父类组织函数 须要修改指向
            this.job = job;

        }

        /*
        CreateStar.prototype = CreatePerson.prototype; //将父类的原型赋给子类,那末子类就获得了父类下一切的属性值,完成了要领的继承 然则这里有对象的援用题目,形成相互过问
        比方:
        CreateStar.prototype.showJob = function(){}
        上面子类的原型增加的要领,那末父类CreatePerson.prototype下面也有了showJob的要领
        */

        //要领的继承应当用for in轮回,将父类的一切属性拷贝给子类,这叫作“拷贝继承”。jQuery也是采纳拷贝继承extend

        function extend(obj1, obj2){
            for(var attr in obj2){
                obj1[attr] = obj2[attr];
            }
        }

        extend(CreateStar.prototype, CreatePerson.prototype )
        var p2 = new CreateStar('黄晓明', '男', '演员')
        p2.showName();

    </script>
</head>
<body>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>继承</title>
    <style></style>
    <script>
        var a = {
            name: '小明'
        };

        //var b = a;
        
        // var b = {};
        // for(var attr in a){
        //  b[attr] = a[attr];
        // }
        // b.name = "小强";
        // alert(a.name);

        //将对象属性的拷贝封装成一个函数
        function extend(obj1, obj2){
            for(var attr in obj2){
                obj1[attr] = obj2[attr];
            }
        }

        var b = {};
        extend(b, a); 
        b.name = '小强';
        alert(b.name);
        alert(a.name);
    </script>
</head>
<body>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>继承</title>
    <style></style>
    <script>
        var a = [1, 2, 3];
        var b = a;
        // b.push(4); //修改 a、b之间援用链条存在
        // alert(a); //1, 2, 3, 4 a被b影响了

        b = [1, 2, 3, 4]; //从新赋值,内存中这个b又从新天生了。a和b之间这个援用的链条已断开,a、b没有关联
        alert(a); //1, 2, 3 a未被影响

        //在for in轮回中,子类原型的要领也直接即是了父类原型的要领,由于要领是函数,也是个对象,为何这类“对象 = 对象”没有相互过问呢?这是由于函数有些特别,不能被修改,只能被从新赋值
    </script>
</head>
<body>
</body>
</html>

继承的拖拽

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        #div1 {width: 100px; height: 100px; background: red; position: absolute;}
        #div2 {width: 100px; height: 100px; background: yellow; position: absolute; left: 100px;}
    </style>
    <script src="jquery-1.11.1.js"></script>
    <script>
        window.onload = function(){
            var d1 = new Drag('div1');
            d1.init();

            var d2 = new ChildDrag('div2');
            d2.init();
        }

        //父类的面向对象的拖拽最先
        function Drag(id){ //父类
            this.obj = document.getElementById(id);
            this.disX = 0;
            this.disY = 0;
        }
        
        Drag.prototype.init = function(){
            var This = this;
            this.obj.onmousedown = function(ev){
                var ev = ev || window.event;
                This.fnDown(ev);

                document.onmousemove = function(ev){
                    var ev = ev || window.event;
                    This.fnMove(ev);
                }
                document.onmouseup = function(){
                    This.fnUp();
                }
                return false;
            }
        }

        Drag.prototype.fnDown = function(ev){
            this.disX = ev.clientX - this.obj.offsetLeft;
            this.disY = ev.clientY - this.obj.offsetTop;
        }
        Drag.prototype.fnMove = function(ev){
            this.obj.style.left = ev.clientX - this.disX + 'px';
            this.obj.style.top = ev.clientY - this.disY + 'px';
        }
        Drag.prototype.fnUp = function(){
            document.onmousemove = null;
            document.onmouseup = null;
        }
        //父类的面向对象的拖拽完毕
        
        //子类继承父类最先
        function ChildDrag(id){ //子类
            Drag.call(this, id);
        }

        extend(ChildDrag.prototype, Drag.prototype);

        //经由历程转变ChildDrap原型下的fnMove,给子类增加了限定拖拽时,元素超越可视区摆布边境的功用
        ChildDrag.prototype.fnMove = function(ev){
            var L = ev.clientX - this.disX;
            var T = ev.clientY - this.disY;

            if(L < 0){
                L = 0;
            } else if (L > document.documentElement.clientWidth - this.obj.offsetWidth){
                L = document.documentElement.clientWidth - this.obj.offsetWidth;
            }

            this.obj.style.left = L + 'px';
            this.obj.style.top = T + 'px';
        }

        function extend(obj1, obj2){
            for(var attr in obj2){
                obj1[attr] = obj2[attr];
            }
        }
        //子类继承父类完毕

    </script>
</head>
<body>
    <div id="div1"></div>
    <div id="div2"></div>
</body>
</html>

继承的其他情势

1、类式继承
运用组织函数(类)继承的体式格局
2、原型继承
借助原型来完成对象继承对象
类式继承

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
    </style>
    <script>
        //类:JS是没有类的观点的,可以把JS中的组织函数看做是类
        //要做属性和要领继承的时刻,要离开继承
        
        function Aaa(){ //父类
            this.name = '小明';
            this.arr = [1, 2, 3];
        }
        Aaa.prototype.showName = function(){
            alert(this.name);
        }

        function Bbb(){ //子类        
        }

        Bbb.prototype = new Aaa(); //这句话就是类式继承
        //只写上面一句话是有题目的,修改了constructor指向。
        //Bbb.prototype.constructor = Bbb; //修改指向题目

        var b1 = new Bbb();
        b1.showName();
        alert(b1.name);
        alert(b1.constructor); //弹出的并非Bbb,而是Aaa。只要写了上面修改指向的那句话,这里才会变成Bbb

        //真正范例的类式继承要用下面几句话:
        // function Bbb(){ //这里只继承了属性
        //  Aaa.call(this)
        // }
        //var F = function(){}; //竖立一个空的组织函数
        //F.prototype = Aaa.prototype;
        //Bbb.prototype = new F(); //这里只继承了要领
        //Bbb.prototype.constructor = Bbb;

        b1.arr.push(4);

        var b2 = new Bbb();
        alert(b2.arr); //[1, 2, 3, 4] 这里看到上面的b1.arr.push(4)影响到了这里 要防备这类题目,应当用上面的类式继承的范例写法才行
    </script>
</head>
<body>
</body>
</html>

原型继承

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>原型继承</title>
    <style>
    </style>
    <script>
        var a = {
            name: '小明'
        }

        var b = cloneObj(a); //让b继承a
        b.name = '小强'; //这一句不会变动a的name,由于这一句在b的下面又新建了一个属性name,值为“小强”
        alert(b.name); //小强
        alert(a.name); //小明

        function cloneObj(obj){
            var F = function(){};
            F.prototype = obj;
            return new F();
        }
    </script>
</head>
<body>
</body>
</html>
  • 拷贝继承:通用型的 有new或无new的时刻都可以

  • 类式继承:合适经由历程new组织函数情势

  • 原型继承:比较合适无new的对象

组件开辟

1、对象的多种表现情势

  • 进步对象的复用性

  • 怎样设置参数和默许参数

  • 例子:拖拽

  • 例子:弹窗

2、什么是组件?

  • 对面向对象的深切运用(UI组件、功用组件)

  • 将设置参数、要领、事宜、三者举行星散

3、竖立自定义事宜

  • 有利于多人合作开辟代码

  • 怎样去挂载自定义事宜与事宜函数

4、例子:基于JQ的选项卡的组件开辟情势
trigger() extend()等要领的运用
5、本课演习
组件开辟的演习
http://tangram.baidu.com/magic/

怎样设置参数和默许参数

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>组件开辟中的参数题目</title>
    <script>
    //用json来处理参数数目题目
        function show(opt){

        }

        show({
            id: 'div1',
            toDown: function(){},
            toUp: function(){}
        });

    //用下面的要领处理参数递次题目
        var a = { //设置参数
            //name: '小明'
            name: '小明'
        }
        var b = { //默许参数
            name: '小强'
        }

        extend(b, a); //当有设置的时刻,走设置,没有设置的时刻,走默许
        alert(b.name);

        function extend(obj1, obj2){
            for(var attr in obj2){
                obj1[attr] = obj2[attr];
            }
        }
    </script>
</head>
<body>
    
</body>
</html>

拖拽的组件开辟

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        #div1 {width: 100px; height: 100px; background: red; position: absolute;}
        #div2 {width: 100px; height: 100px; background: yellow; position: absolute; left: 100px;}
        #div3 {width: 100px; height: 100px; background: blue; position: absolute; left: 200px;}
        #div4 {width: 100px; height: 100px; background: green; position: absolute; left: 300px;}
    </style>
    <script src="jquery-1.11.1.js"></script>
    <script>
    /*
        组件开辟:像兄弟之间的关联(代码复用的一种情势)
    */
        window.onload = function(){
            var d1 = new Drag();
            d1.init('div1');

            var d2 = new Drag();
            d2.init('div2', { //设置参数
                toDown: function(){
                    document.title = 'hello';
                }
            });

            var d3 = new Drag();
            d3.init('div3', { //设置参数
                toDown: function(){
                    document.title = '妙味';
                },
                toUp: function(){
                    document.title = '教室';
                }
            });

            var d4 = new Drag();
            d4.init('div4', { //设置参数
                toUp: function(){
                    document.title = 'byebye';
                }
            });
        }

        function Drag(){
            this.obj = null;
            this.disX = 0;
            this.disY = 0;

            this.settings = { //默许参数
                //id不应当属于设置参数当中,它属于必填项
                toDown: function(){},
                toUp: function(){}
            }
        }
        
        Drag.prototype.init = function(id, opt){
            var This = this;
            this.obj = document.getElementById(id);

            extend(this.settings, opt); //用设置掩盖默许

            this.obj.onmousedown = function(ev){
                var ev = ev || window.event;
                This.fnDown(ev);

                This.settings.toDown();

                document.onmousemove = function(ev){
                    var ev = ev || window.event;
                    This.fnMove(ev);
                }
                document.onmouseup = function(){
                    This.fnUp();
                    This.settings.toUp();
                }
                return false;
            }
        }

        Drag.prototype.fnDown = function(ev){
            this.disX = ev.clientX - this.obj.offsetLeft;
            this.disY = ev.clientY - this.obj.offsetTop;
        }
        Drag.prototype.fnMove = function(ev){
            this.obj.style.left = ev.clientX - this.disX + 'px';
            this.obj.style.top = ev.clientY - this.disY + 'px';
        }
        Drag.prototype.fnUp = function(){
            document.onmousemove = null;
            document.onmouseup = null;
        }

        function extend(obj1, obj2){
            for(var attr in obj2){
                obj1[attr] = obj2[attr];
            }
        }

    </script>
</head>
<body>
    <div id="div1"></div> <!-- 赤色方块是老大 -->
    <div id="div2"></div> <!-- 黄色方块是老二 黄色的按下以后title有一个变化 -->
    <div id="div3"></div> <!-- 老三 按下title变化,抬起title变化 -->
    <div id="div4"></div> <!-- 老四 鼠标抬起时title有变化 -->
</body>
</html>

弹窗的组件开辟

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>弹窗的组件开辟</title>
    <style>
        * {margin : 0; padding; 0}
        .login {background: white; border: 1px #000 solid; position: absolute; left: 0; top: 0; z-index: 2;}
        .title {height: 30px; background: gray; color: white;}
        .title .close {float: right;}
        #mask {width: 500px; height: 500px; background: black; filter: alpha(oapcity=50); opacity: 0.5; position: absolute; left: 0; top: 0; z-index: 1;}
    </style>
    <script>
        window.onload = function(){
            var aInput = document.getElementsByTagName('input');

            aInput[0].onclick = function(){
                var d1 = new Dialog();
                d1.init({//设置参数
                    iNow: 0,
                    title: '上岸'
                });
            }

            aInput[1].onclick = function(){
                var d2 = new Dialog();
                d2.init({//设置参数
                    iNow: 1,
                    w : 100,
                    h : 400,
                    dir: 'right',
                    title: '通告'
                });
            }

            aInput[2].onclick = function(){
                var d3 = new Dialog();
                d3.init({//设置参数
                    iNow: 2,
                    mask: true
                });
            }
        }

        function Dialog(){
            this.oLogin = null;
            this.settings = { //默许参数
                w: 300,
                h: 300,
                dir: 'center',
                title: '',
                mask: false
            }
        }

        Dialog.prototype.json = {}; //防备增加多个弹窗

        Dialog.prototype.init = function(opt){

            extend(this.settings, opt);

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

            if(this.json[opt.iNow]){ //防备增加多个弹窗
                this.create();
                this.fnClose();

                if(this.settings.mask){
                    this.createMask();
                }

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

        }

        Dialog.prototype.create = function(){

            this.oLogin = document.createElement('div');
            this.oLogin.className = 'login';
            this.oLogin.innerHTML = '<div class="title"><span>' + this.settings.title + '</span><span class="close">X</span></div><div class="content"></div>';
            document.body.appendChild(this.oLogin);
            this.setData();

        }

        Dialog.prototype.setData = function(){
            this.oLogin.style.width = this.settings.w + 'px';
            this.oLogin.style.height = this.settings.h + 'px';

            if(this.settings.dir == 'center'){
                this.oLogin.style.left = (viewWidth() - this.oLogin.offsetWidth)/2 + 'px';
                this.oLogin.style.top = (viewHeight() - this.oLogin.offsetHeight)/2 + 'px';
            } else if (this.settings.dir == 'right'){
                this.oLogin.style.left = (viewWidth() - this.oLogin.offsetWidth) + 'px';
                this.oLogin.style.top = (viewHeight() - this.oLogin.offsetHeight) + 'px';
            }

        }

        Dialog.prototype.fnClose = function(){
            var oClose = this.oLogin.getElementsByTagName('span')[1];
            var This = this;
            oClose.onclick = function(){
                document.body.removeChild(This.oLogin);
                if(This.settings.mask){
                    document.body.removeChild(This.oMask);
                }

                This.json[This.settings.iNow] = true;
            }
        }

        Dialog.prototype.createMask = function(){
            var oMask = document.createElement('div');
            oMask.id = 'mask';
            document.body.appendChild(oMask);
            this.oMask = oMask;

            oMask.style.width = viewWidth() + 'px';
            oMask.style.height = viewHeight() + 'px';
        }

        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="login">
        <div class="title">
            <span>题目</span><span class="close">X</span>
        </div>
        <div class="content"></div>
    </div> -->
    <!-- <div id="mask"></div> -->
</body>
</html>

明白自定义事宜

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>自定义事宜</title>
    <script>
        // 自定义事宜:主如果跟函数有关联,让函数可以具有事宜的某些特征

        // 三个人都针对show来增加功用。都增加到一个处所会乱,因而三个人离开来写
        /*
        function show(){
            alert(1); //第一个人写
        }

        function show(){
            alert(2); //第二个人写
        }

        function show(){
            alert(3); //第三个人写
        }

        show(); //只能实行第三个人写的,由于函数不能修改只能掩盖
        */
        
        //看看是不是能让函数具有事宜的特征,多人写的可以绑定上去,就处理了多人合作的题目。道理就如以下情况。固然以下代码不是增加自定义事宜的代码,只是为了轻易明白:
        /*
        window.addEventListener('show', function(){
            alert(1); //第一个人写的
        }, false);
        window.addEventListener('show', function(){
            alert(2); //第二个人写的
        }, false);
        window.addEventListener('show', function(){
            alert(3); //第三个人写的
        }, false);

        show(); //主动触发自定义事宜
        */
    </script>
</head>
<body>
    
</body>
</html>

用原生js完成自定义事宜

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>自定义事宜</title>
    <script>
    //自定义事宜重点在于将函数和元素以及事宜称号竖立关联,在实行某个函数的时刻,主动触发某个事宜称号下面相干的一切函数
        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(){ //这里的show就是个自定义事宜
                alert(3);
            })

            bindEvent(oSpan, 'show', function(){ //这里的show就是个自定义事宜
                alert(4);
            })

            bindEvent(oSpan, 'hide', function(){ //这里的show就是个自定义事宜
                alert(5);
            })

            fireEvent(oSpan, 'show'); //主动触发,弹出3, 4
            fireEvent(oDiv, 'click'); //主动触发,弹出1, 2
        }



        function bindEvent(obj, events, fn){

            //fn: 看做一本书 《西游记》
            //obj: 相当于藏书楼的楼层 文学楼
            //events: 相当于书架 古典文学书架

            obj.listeners = obj.listeners || {}; //先找到楼层,没有楼层就竖立楼层
            obj.listeners[events] = obj.listeners[events] || []; //再找到书架,没有书架就竖立书架
            obj.listeners[events].push(fn); //把fn这本书放到书架上
            /* 经由历程以上的体式格局,将obj,events和fn竖立了关联*/

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

        function fireEvent(obj, events){ //主动触发自定义事宜
            for(var i=0; i<obj.listeners[events].length; i++){
                obj.listeners[events][i]();
            }
        }

    </script>
</head>
<body>
    <div id="div1">div</div>
    <span id="span1">span</span>
</body>

设置、要领、自定义事宜星散

——正规组件的写法——基于拖拽的组件举行的修改

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>自定义事宜的拖拽组件</title>
    <style>
        #div1 {width: 100px; height: 100px; background: red; position: absolute;}
        #div2 {width: 100px; height: 100px; background: yellow; position: absolute; left: 100px;}
        #div3 {width: 100px; height: 100px; background: blue; position: absolute; left: 200px;}
        #div4 {width: 100px; height: 100px; background: green; position: absolute; left: 300px;}
    </style>
    <script src="jquery-1.11.1.js"></script>
    <script>
        window.onload = function(){
            var d1 = new Drag();
            d1.init('div1');

            var d2 = new Drag();
            d2.init('div2');

            bindEvent(d2, 'toDown', function(){
                document.title = 'hello';
            });
            
            bindEvent(d2, 'toDown', function(){ //新来的一个同事扩大d2的toDown事宜的时刻,更轻易
                document.body.style.background = 'black';
            })

            var d3 = new Drag();
            d3.init('div3');

            bindEvent(d3, 'toDown', function(){
                document.title = '妙味';
            })
            bindEvent(d3, 'toUp', function(){
                document.title = '教室';
            })

            var d4 = new Drag();
            d4.init('div4');

            bindEvent(d4, 'toUp', function(){
                document.title = 'byebye';
            })
        }

        function Drag(){
            this.obj = null;
            this.disX = 0;
            this.disY = 0;

            this.settings = { 
                
            }
        }
        
        Drag.prototype.init = function(id, opt){
            var This = this;
            this.obj = document.getElementById(id);

            extend(this.settings, opt); 

            this.obj.onmousedown = function(ev){
                var ev = ev || window.event;
                This.fnDown(ev);
                fireEvent(This, 'toDown');

                document.onmousemove = function(ev){
                    var ev = ev || window.event;
                    This.fnMove(ev);
                }
                document.onmouseup = function(){
                    This.fnUp();
                    fireEvent(This, 'toUp');
                }
                return false;
            }
        }

        Drag.prototype.fnDown = function(ev){
            this.disX = ev.clientX - this.obj.offsetLeft;
            this.disY = ev.clientY - this.obj.offsetTop;
        }
        Drag.prototype.fnMove = function(ev){
            this.obj.style.left = ev.clientX - this.disX + 'px';
            this.obj.style.top = ev.clientY - this.disY + 'px';
        }
        Drag.prototype.fnUp = function(){
            document.onmousemove = null;
            document.onmouseup = null;
        }

        function extend(obj1, obj2){
            for(var attr in obj2){
                obj1[attr] = obj2[attr];
            }
        }

        function bindEvent(obj, events, fn){

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

            if(obj.nodeType){ //假如传进来的是DOM元素的话,走着下面;假如传进来的不是DOM,是对象的话,就不走下面,只走上面了
                if(obj.addEventListener){
                    obj.addEventListener(events, fn, false);
                } else {
                    obj.attachEvent('on' + events, fn);
                }   
            }
        }

        function fireEvent(obj, events){ 
            if(obj.listeners &amp;&amp; obj.listeners[events]){
                for(var i=0; i<obj.listeners[events].length; i++){
                    obj.listeners[events][i]();
                }
            }
        }

    </script>
</head>
<body>
    <div id="div1"></div> 
    <div id="div2"></div> 
    <div id="div3"></div> 
    <div id="div4"></div> 
</body>
</html>

用JQ完成选项卡的组件开辟

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>基于JQ的选项卡组件开辟</title>
    <style>
        html, body {margin: 0; padding: 0;}
        #div1 div, #div2 div, #div3 div, #div4 div {width: 200px; height: 200px; border: 1px solid #000; display: none;}
        #div1 .active, #div2 .active, #div3 .active, #div4 .active {background: red;}
    </style>
    <script src="jquery-1.11.1.js"></script>
    <script>
    /*
        title: 基于JQ的选项卡组件
        Options: 
            - event 
            - delay
        Methods: 
            - nowSel() - 设置最先的tab数
            - getContent() - 猎取当前内容
        Events:
            - beforeClick 点击前触发
            - afterClick 点击后触发
    */

    // JQ中的主动触发:trigger()

        $(function(){

            var t1 = new Tab();
            t1.init('div1', {});

            var t2 = new Tab();
            t2.init('div2', {
                event: 'mouseover'
            });

            var t3 = new Tab();
            t3.init('div3', {
                event: 'mouseover',
                delay: 200
            });

            var t4 = new Tab();
            t4.init('div4', {});
            t4.nowSel(2);

            $('#input1').click(function(){
                alert(t4.getContent());
            })

            $(t4).on('beforeClick', function(){
                alert(t4.getContent());
            })

            $(t4).on('afterClick', function(){
                alert(t4.getContent());
            })

        })

        function Tab(){
            this.oParent = null;
            this.aInput = null;
            this.aDiv = null;
            this.iNow = 0;

            this.settings = { //默许参数
                event: 'click',
                delay: 0
            }
        }

        Tab.prototype.init = function(oParent, opt){
            $.extend(this.settings, opt);
            this.oParent = $('#' + oParent);
            this.aInput = this.oParent.find('input');
            this.aDiv = this.oParent.find('div');

            this.change();
        }

        Tab.prototype.change = function(){
            var This = this;
            var timer = null;

            this.aInput.on(this.settings.event, function(){

                if(This.settings.event == 'mouseover' &amp;&amp; This.settings.delay){
                    var _this = this;

                    timer = setTimeout(function(){
                        show(_this);
                    }, This.settings.delay)
                } else {
                    show(this);
                }
                
            }).mouseout(function(){
                clearTimeout(timer);
            });

            function show(obj){

                $(This).trigger('beforeClick');

                This.aInput.attr('class', '');
                This.aDiv.css('display', 'none');
                $(obj).attr('class', 'active');
                This.aDiv.eq($(obj).index()).css('display', 'block');

                This.iNow = $(obj).index();

                $(This).trigger('afterClick');
            }

            Tab.prototype.nowSel = function(index){
                this.aInput.attr('class', '');
                this.aDiv.css('display', 'none');
                this.aInput.eq(index).attr('class', 'active');
                this.aDiv.eq(index).css('display', 'block');

                this.iNow = index;
            }
            Tab.prototype.getContent = function(){
                return this.aDiv.eq(this.iNow).html();
            }
        }
    </script>
</head>
<body>
    <div id="div1">
        <input type="button" value="1" class="active">
        <input type="button" value="2">
        <input type="button" value="3">
        <div style="display: block">111111</div>
        <div>222222</div>
        <div>333333</div>
    </div>
    <div id="div2">
        <input type="button" value="1" class="active">
        <input type="button" value="2">
        <input type="button" value="3">
        <div style="display: block">111111</div>
        <div>222222</div>
        <div>333333</div>
    </div>
    <div id="div3">
        <input type="button" value="1" class="active">
        <input type="button" value="2">
        <input type="button" value="3">
        <div style="display: block">111111</div>
        <div>222222</div>
        <div>333333</div>
    </div>
    <div id="div4">
        <input type="button" value="1" class="active">
        <input type="button" value="2">
        <input type="button" value="3">
        <div style="display: block">111111</div>
        <div>222222</div>
        <div>333333</div>
    </div>
    <input type="button" value="点击" id="input1">
</body>
</html>
    原文作者:eve0803
    原文地址: https://segmentfault.com/a/1190000005059443
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞