JS基礎入門篇(三十四)— 面向對象(一)

1.對象

  1. 對象的定義 : 對象 是 由 鍵值對 組成的無序集合。
  2. 建立對象兩種方法 :
    方法一 : 字面量方法html

    var obj = {name: "k"};

    方法二 : new Object( ) 構造函數建立windows

    var a = new Object();
       a.name = "zm";
       console.log( a ); // {name: "zm"}

2.面向對象和麪向過程的比較

若是 想要把大象放進冰箱。數組

1.面向過程思想的邏輯思惟是:瀏覽器

1.打開冰箱
2.把大象放入冰箱
3.關上冰箱

解析: 面向過程思想的邏輯思惟是,咱們先作什麼,而後作什麼,最後作什麼。是分步驟一步一步往下走。性能優化

疑問:🤔️也許有許多小夥伴以爲,面向過程很符合咱們的思惟邏輯啊。的確如此,可是面向過程的缺點是擴展性和複用性不好。若是咱們想要:
把獅子放入冰箱app

1.打開冰箱
2.拿出大象
2.把獅子放入冰箱
3.關上冰箱

把老虎放入冰箱函數

1.打開冰箱
2.拿出獅子
2.把老虎放入冰箱
3.關上冰箱

2.面向對象思想的邏輯思惟是:性能

冰箱:
        打開
        關上
        清空            
        
    動物: 
        進入

3.批量建立對象

1.經過調用函數建立對象。優化

<script>
    //函數做用:建立一個對象,帶有name和age屬性,say方法。
    function createObj( name,age ){
        var o={};//建立一個新的對象
        o.name=name;//爲對象添加屬性
        o.age=age;//爲對象添加屬性
        o.say = function(){//爲對象添加方法
            console.log( "我是人" );
        };
        return o;
    }

    var obj = createObj("kimoo",28);
    console.log( obj );//{name: "kimoo", age: 28, say: ƒ}

    var obj2 = createObj("zm",38);
    console.log( obj2 );//{name: "zm", age: 38, say: ƒ}

    console.log(obj.say===obj2.say);//false
</script>

解析: say 方法,每次調用函數都會生成一個新的對象,會生成新的say( )方法。因此,每次調用createObj( name,age ); ,都會生成新的say( )方法,可是每一個say方法的功能都同樣,這樣對性能有影響。this

2.經過調用函數建立對象,性能優化。

<script>
//    批量建立對象
    var obj = createObj("kimoo",28); 
    console.log( obj );
    obj.say();
    
    var obj2 = createObj("zm",38); 
    console.log( obj2 );
    obj2.say();
    
    console.log( obj.say === obj2.say ); // true
    
    function say(){
        console.log( "我是人" );
    }
    
    function createObj( name,age ){
        var o = {};
        o.name = name;
        o.age = age;
        o.say = say;
        return o;
    }
</script>

3.函數的比較

var fn1 = function(){
            alert(1);
        };
        var fn2 = function(){
            alert(1);
        };
        console.log( fn1 === fn2 ); // false
//---------------------------------------------------
        var temp = function(){alert(2)};
        var fn3 = temp;
        var fn4 = temp;
        console.log( fn3 === fn4 );// true

解釋:不管如何定義一個函數,JS解釋器都會把它翻譯成一個Function對象。因此每次建立一個自定義函數,都會建立一個新的對象。例如:fn1和 fn2變量都是存儲對象的地址,雖然建立新對象的內容是同樣的,可是在瀏覽器解析的時候,它會給對象建立一個地址。fn1和fn2存儲的地址不相等,故fn1和fn2不相等。 fn3存儲是temp接受的對象的地址,fn4存儲也是temp接受的對象的地址。故fn3和fn4不相等。

4.構造函數

狀況一:沒有返回值,打印的是undefined。

<script>
    function fn(){
        console.log( 1 );
    }

    var res1 = fn();
    console.log( res1 );//undefined

解析:當函數沒有返回值的時候,將函數調用賦給變量,打印的值是undefined。由於沒有返回值。

狀況二:使用 new 來調用函數,沒有返回值,打印的是{}(空對象)。

使用 new 來調用函數
            函數內部會自動return 一個對象
        若是函數內部使用了 return X
            若是 X 是一個 非null 的 對象res
                那麼經過new 調用 ,返回的是 res
            
            若是 X 是 非對象 或者 null
                那麼經過new 調用 ,返回的是 {}

舉例說明:

<script>
    function fn(){
        console.log( 1 );
//        return 2;//當return的值是2,console.log( res2 )打印結果是{}
//        return null;//當return的值是null,console.log( res2 )打印結果是{}
//        return {b:3};//當return的值是{b:3},console.log( res2 )打印結果是{b:3}
    }

    var res2 = new fn();
    console.log( typeof res2 );//object
    console.log( res2 );
</script>

進一步對狀況二說明:使用 new 來調用函數的過程

使用 new 來調用函數
第一步:函數內部會自動爲咱們建立一個對象
第二步函數內部的 this 指向會變爲 當前構造函數生成的對象
第三步:會自動return

<script>
    function fn(name, age){
//第一步        var obj = {};
        console.log( this );//第二步:這個this指向的是生成的對象res。打印結果是:fn{}
        this.name = name;
        this.age = age;
    }
//    fn();  //若是是這樣直接調用,指向的是windows。
    
    var res = new fn("kimoo",28);
//        此處: 經過new 調用fn ,
//            fn 被稱爲 構造函數
//            res 是 fn 的 實例
//            整個過程 被稱爲 實例化
            
    console.log( res ); //fn {name: "kimoo", age: 28}
</script>

5.經過構造函數批量建立對象

約定: 構造函數的大駝峯寫法

<script>
    function CreatePerson( name,age ){
        this.name = name;
        this.age = age;
        this.say = function(){
            console.log( "我是人");
        }
    }
    
    var p1 = new CreatePerson("kimoo",28);
    console.log( p1 );//{name: "kimoo", age: 28, say: ƒ}
    p1.say();//我是人
    
    var p2 = new CreatePerson("zm",38);
    console.log( p2 );//{name: "zm", age: 38, say: ƒ}
    p2.say();//我是人
    console.log( p1.say === p2.say ); //false 性能上的浪費:方法並無共享。爲解決這個問題,除了上面把函數提取出來的方法,可使用prototype。
</script>

6.prototype 原型

prototype (原型):當一個函數被申明的時候,該函數下默認有一個屬性:prototype,該屬性的值是一個對象。

<script>
    function CreatePreson(){}
    console.dir( CreatePreson );
</script>

結果爲:

圖片描述

當咱們去調用一個對象的屬性或者方法的時候,
若是該對象自身沒有該屬性或方法,則會調用到該對象 的 構造函數的prototype的屬性或方法

把經過構造函數構造出來的對象,共有的方法或者屬性,放在prototype身上,可以達到性能節約的辦法。

<script>
    function CreatePreson(){
    }
    CreatePreson.prototype.say = function(){console.log(1);};
    CreatePreson.prototype.name = "k";

    var p = new CreatePreson();
    p.say();// 當咱們去調用一個對象的屬性或者方法的時候,自身沒有的時候,找構造函數的prototype的屬性或者方法
    console.log( p.name ); // 當咱們去調用一個對象的屬性或者方法的時候,自身沒有的時候,找構造函數的prototype的屬性或者方法

    var p2 = new CreatePreson();
    p2.say();// 當咱們去調用一個對象的屬性或者方法的時候,自身沒有的時候,找構造函數的prototype的屬性或者方法
    console.log( p2.name ); // 當咱們去調用一個對象的屬性或者方法的時候,自身沒有的時候,找構造函數的prototype的屬性或者方法

    console.log( p.say === p2.say );//true
    
    
</script>

7.__proto__

__proto__
    當一個對象被建立的時候,該對象會自動被添加上一個屬性:__proto__,他的值也是一個對象,而且該屬性 就是 當前這個對象的構造函數的prototype
    對象.__proto__ === 構造函數.prototype
<script>
    function CreatePreson(){};
    var p1 = new CreatePreson();
    console.log( CreatePreson.prototype === p1.__proto__ );//true

8.選項卡(用面向對象的思想寫一遍)

查看選項卡

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="box"></div>
<script>
    function CraetTab(param) {
        this.el = param.el;
        this.buttonText = param.buttonText;//button按鈕的內容
        this.contentText = param.contentText;//div的內容
        this.button = [];//生成button元素用button數組存儲
        this.content = [];//生成div元素用div數組存儲
        this.current = 0;//記錄當前顯示的button和div
        this.autoPlay = param.autoPlay!==undefined?param.autoPlay:true;//默認自動播放
    }
    CraetTab.prototype.init=function () {
        //生成對應style樣式
        var style=document.createElement("style");
        style.innerHTML="#"+this.el.id+" .active{background-color: red;}#"+this.el.id+" .show{display: block;}#"+this.el.id+" div{display: none;}";
        document.body.appendChild(style);

        //根據建立對象的buttonText個數生成button
        //並把每個生成的button塞入數組中
        //將生成的button添加到box中
        for(var i=0;i<this.buttonText.length;i++){
            var btu=document.createElement("button");
            btu.innerHTML=this.buttonText[i];
            this.button.push(btu);
            this.el.appendChild(btu);
        }

        //根據建立對象的contentText個數生成div
        //並把每個生成的div塞入數組中
        //將生成的div添加到box中
        for(var i=0;i<this.contentText.length;i++){//生成div
            var div=document.createElement("div");
            div.innerHTML=this.contentText[i];
            this.content.push(div);
            this.el.appendChild(div);
        }

        //若是this.autoPlay爲真,則開啓定時器,讓選項卡自動播放
        if(this.autoPlay){
            var num=0;
            var that=this;//因爲在setInterval事件中this就指的是當前的window。因此要在外部存儲指向對象的this。
            setInterval(function () {
                for(var i=0;i<that.buttonText.length;i++){
                    that.button[i].classList.remove("active");
                    that.content[i].classList.remove("show");
                }
                that.button[num].classList.add("active");
                that.content[num].classList.add("show");
                num++;
                num%=that.buttonText.length;
            },1000)
        }
        this.setCss();
        this.addEvent();
    };
    
    //大清洗,給當前顯示的div和button添加樣式
    CraetTab.prototype.setCss=function () {
        for(var i=0;i<this.buttonText.length;i++){
            this.button[i].classList.remove("active");
            this.content[i].classList.remove("show");
        }
        this.button[this.current].classList.add("active");
        this.content[this.current].classList.add("show");

    };
    //給button添加點擊事件,點擊哪一個就將that.current的值改爲對應button的索引值。
    CraetTab.prototype.addEvent=function () {
        var that=this;//因爲在button點擊事件中this就指的是當前的button。因此要在外部存儲指向對象的this。
        for(var i=0;i<this.buttonText.length;i++){
            this.button[i].index=i;
             this.button[i].onclick=function () {
                 that.current= this.index;
                 that.setCss();
             }
        }
    };
    var box=document.getElementById("box");
    var t1 =new CraetTab({
        el: box,
        buttonText: [
            "按鈕1",
            "按鈕2",
            "按鈕3"
        ],
        contentText:[
            "內容1",
            "內容2",
            "內容3"
        ],
        autoPlay:false
    });
    t1.init();
</script>
</body>
</html>
相關文章
相關標籤/搜索