前端基本功:JS(十三)閉包、面向對象

函數的復習:

  • 自定義函數和調用函數
<script>
  //  自定義函數
  fun();  // 調用函數    放到哪個位置都可以
  function fun() {
      console.log(3);
  }

  var fn = function() {
        console.log(4);
    }
  fn();   // 調用函數  必須再函數聲明的下面 先聲明后使用

</script>
  • 全局變量和局部變量
<script>
   //   變量的作用域   全局變量 和 局部變量
   var key = "你好嗎";   // 全局變量
    function fun() {
        var num = 10;   // 再函數內部聲明的   內部變量
        console.log(num);
        console.log(key);
    }
    fun();
    console.log(num);
</script>

閉包

在程序語言中,所謂閉包醉鳖,是指語法域位于某個特定的區(qū)域,具有持續(xù)參照(讀寫)位于該區(qū)域內自身范圍之外的執(zhí)行域上的非持久型變量值能力的段落哮内。這些外部執(zhí)行域的非持久型變量神奇地保留他們在閉包最初定義(或創(chuàng)建)時的值盗棵。

白話: 我們可以用一個函數 去訪問 另外一個函數的內部變量的方式就是閉包。

內部變量 是 局部變量 那我們知道,局部變量是不可以為別人隨便使用也纹因。

閉包原理
變量的作用鏈域

閉包常用寫法★★★★★

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

</body>
</html>
<script>
    function outFun() {
        var num = 10;
        function inFun() {
            console.log(num);   // 非常正常的寫法
        }
        return inFun;   // !!核心E缥荨! 這里無括號即 返回的是 inFun函數體  瞭恰;若加括號返回的是結果
    }
    // 使用
    console.log(outFun());
    var demo = outFun();   // 看清楚 此處加了小括號
      // outFun()    返回的是      function inFun() {console.log(num); }
    //  相當于 這句話 var demo = function inFun() {console.log(num); }
    demo();
    
</script>

其實每個函數都算一個小閉包:

加強閉包的認識(面試題):

<script>    
    function outerFun()  // 外部函數
    {
        var a=0;    // 清空
        function innerFun()  // 內部函數
        {
            a++;
            alert(a);
        }
        return innerFun;  // 注意這里  核心
    }
    var obj=outerFun();   // 1  2
    obj();  obj();
    var obj2= outerFun();
    obj2();  obj2();   // 1  2
    // 結果是 什么 屯曹?
    function outerFun()  // 外部函數
    {
        var a=0;    // 清空
        return  function()  // 內部函數
        {
            a++;
            alert(a);
        }

    }
</script>

結果是1,2 1,2

這些外部執(zhí)行域的非持久型變量神奇地保留他們在閉包最初定義(或創(chuàng)建)時的值。

閉包的優(yōu)缺點 :

優(yōu)點:不產生全局變量惊畏,實現屬性私有化恶耽。
缺點:閉包中的數據會常駐內存,在不用的時候要刪掉否則會導致內存溢出陕截。

閉包原理★★★★★

<script>
    function outFun() {
        var num = 10;
        function inFun() {   //  內部的函數可以使用外部的函數 變量
            console.log(num);
        }
        return inFun;  // 注意:不帶括號2道狻!不帶括號返回函數體农曲,帶括號返回函數值
    }
    var obj = outFun();
    // obj = function inFun() { console.log(num)}
    obj();

</script>

閉包的價值——傳參

閉包的傳參:

<script>
    function Fun(x) {
        return function(y) {
            console.log(x+y);
        }
    }

    var obj = Fun(4);
    // 相當于  obj = function() {console.log(x)}
    obj();
    obj(2);
</script>

結果:NAN 6

事件傳遞參數案例:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        div {
            position: absolute;
            left: 0;
            background-color: pink;
            width: 100px;
            height: 100px;
        }
    </style>
</head>
<body>
<button id="btn1">右走</button>
<button id="btn2">左走</button>
<div id="box"></div>
</body>
</html>
<script>
    var btn1 = document.getElementById("btn1");
    var btn2 = document.getElementById("btn2");
    var box = document.getElementById("box");
   /*之前的寫法:
    var speed = 5;
    btn1.onclick = function() {
        box.style.left = box.offsetLeft + speed+ "px";
    }
    btn2.onclick = function() {
        box.style.left = box.offsetLeft + speed+ "px";
    }*/
   /* btn1.onclick = function() {
        move(5);
    }
    btn2.onclick = function() {
        move(-5);
    }
    function move(speed) {
        box.style.left = box.offsetLeft + speed + "px";
    }*/
    function move(speed) {
        return function() {
            box.style.left = box.offsetLeft + speed + "px";
        }
    }
    btn1.onclick = move(5);
    btn2.onclick = move(-5);

</script>

閉包版本的TAB欄切換

備注:<a href="http://www.reibang.com/p/7658c093e411" target="" >不用閉包的已于JS(四)介紹過 </a>

多個tab欄(閉包)

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        *{margin:0;padding:0;}
        ul{list-style:none;}
        .box {
            width: 350px;
            height: 300px;
            border:1px solid #ccc;
            margin: 100px auto;
            overflow: hidden;
        }
        .mt span {
            display: inline-block;
            width: 80px;
            height: 30px;
            background-color: pink;
            text-align: center;
            line-height: 30px;
            cursor: pointer;
        }
        .mt span.current {
            background-color: purple;
        }
        .mb li {
            width: 100%;
            height: 270px;
            background-color: purple;
            display: none;
        }
        .mb li.show {
            display: block;
        }
    </style>
    <script>
        window.onload = function(){
            //要想多個盒子不相互影響 社搅,我們可以通過id 給他們分開
            //封裝tab欄切換函數
            function tab(obj){
                var target = document.getElementById(obj);
                var spans = target.getElementsByTagName("span");
                var lis = target.getElementsByTagName("li");
                for(var i=0;i<spans.length;i++)
                {
                    //  spans[i].index = i;
                    spans[i].onmouseover =  function (num) {
                        return function(){
                            for(var j=0; j<spans.length;j++)
                            {
                                spans[j].className = "";
                                lis[j].className = "";
                            }
                            spans[num].className = "current";
                            lis[num].className = "show";
                        }
                    }(i);


                }
            }
            tab("one");
            tab("two");
            tab("three");
         }
    </script>
</head>
<body>
<div class="box" id="one">
    <div class="mt">
        <span class="current">新聞</span>
        <span>體育</span>
        <span>娛樂</span>
        <span>八卦</span>
    </div>
    <div class="mb">
        <ul>
            <li class="show">新聞模塊</li>
            <li>體育模塊</li>
            <li>娛樂模塊</li>
            <li>八卦模塊</li>
        </ul>
    </div>
</div>
<div class="box" id="two">
    <div class="mt">
        <span class="current">新聞</span>
        <span>體育</span>
        <span>娛樂</span>
        <span>八卦</span>
    </div>
    <div class="mb">
        <ul>
            <li class="show">新聞模塊</li>
            <li>體育模塊</li>
            <li>娛樂模塊</li>
            <li>八卦模塊</li>
        </ul>
    </div>
</div>
<div class="box" id="three">
    <div class="mt">
        <span class="current">新聞</span>
        <span>體育</span>
        <span>娛樂</span>
        <span>八卦</span>
    </div>
    <div class="mb">
        <ul>
            <li class="show">新聞模塊</li>
            <li>體育模塊</li>
            <li>娛樂模塊</li>
            <li>八卦模塊</li>
        </ul>
    </div>
</div>
</body>
</html>

tab欄(閉包節(jié)流)

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        *{margin:0;padding:0;}
        ul{list-style:none;}
        .box {
            width: 350px;
            height: 300px;
            border:1px solid #ccc;
            margin: 100px auto;
            overflow: hidden;
        }
        .mt span {
            display: inline-block;
            width: 80px;
            height: 30px;
            background-color: pink;
            text-align: center;
            line-height: 30px;
            cursor: pointer;
        }
        .mt span.current {
            background-color: purple;
        }
        .mb li {
            width: 100%;
            height: 270px;
            background-color: purple;
            display: none;
        }
        .mb li.show {
            display: block;
        }
    </style>
    <script>
        window.onload = function(){
            //要想多個盒子不相互影響 ,我們可以通過id 給他們分開
            //封裝tab欄切換函數
            function tab(obj){
                var target = document.getElementById(obj);
                var spans = target.getElementsByTagName("span");
                var lis = target.getElementsByTagName("li");
                for(var i=0;i<spans.length;i++)
                {
                    //  spans[i].index = i;
                    var timer = null;
                    spans[i].onmouseover =  function (num) {
                        return function(){
                            clearTimeout(timer);
                            timer = setTimeout(function(){
                                for(var j=0; j<spans.length;j++)
                                {
                                    spans[j].className = "";
                                    lis[j].className = "";
                                }
                                spans[num].className = "current";
                                lis[num].className = "show";
                            },300)

                        }
                    }(i);
                    spans[i].onmouseout = function() {
                        clearTimeout(timer);
                    }


                }
            }
            tab("one");
            tab("two");
            tab("three");
         }
    </script>
</head>
<body>
<div class="box" id="one">
    <div class="mt">
        <span class="current">新聞</span>
        <span>體育</span>
        <span>娛樂</span>
        <span>八卦</span>
    </div>
    <div class="mb">
        <ul>
            <li class="show">新聞模塊</li>
            <li>體育模塊</li>
            <li>娛樂模塊</li>
            <li>八卦模塊</li>
        </ul>
    </div>
</div>
<div class="box" id="two">
    <div class="mt">
        <span class="current">新聞</span>
        <span>體育</span>
        <span>娛樂</span>
        <span>八卦</span>
    </div>
    <div class="mb">
        <ul>
            <li class="show">新聞模塊</li>
            <li>體育模塊</li>
            <li>娛樂模塊</li>
            <li>八卦模塊</li>
        </ul>
    </div>
</div>
<div class="box" id="three">
    <div class="mt">
        <span class="current">新聞</span>
        <span>體育</span>
        <span>娛樂</span>
        <span>八卦</span>
    </div>
    <div class="mb">
        <ul>
            <li class="show">新聞模塊</li>
            <li>體育模塊</li>
            <li>娛樂模塊</li>
            <li>八卦模塊</li>
        </ul>
    </div>
</div>
</body>
</html>

屏幕縮放事件

(非閉包):

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<div id="demo"></div>
</body>
</html>
<script>
    var num = 0;
    var demo = document.getElementById("demo")
    window.onresize = function() {  // ie8 等瀏覽器 每觸發(fā)一次 乳规,執(zhí)行兩次
        num++;
       demo.innerHTML = window.innerWidth || document.documentElement.clientWidth;  // 得到當前的屏幕寬度
        console.log(num);
    }
</script>

(閉包版的函數節(jié)流):

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<div id="demo"></div>
</body>
</html>
<script>
    var num = 0;
    var demo = document.getElementById("demo")
    window.onresize = throttle(function(){
        demo.innerHTML = window.innerWidth || document.documentElement.clientWidth;
        num++;
        console.log(num);
    },300);
    function throttle(fn,delay) {  // 閉包  節(jié)流
         var timer = null;
         return function() {
             clearTimeout(timer);
             timer = setTimeout(fn,delay);
         }
    }
</script>

對象(object)

對象是什么形葬?
基本數據類型 string number boolean null undefined

Array 對象
對象數據類型: 對象就是帶有屬性和方法的 數據類型

但是有個問題, 我們想要某些屬性或者方法的時候暮的,用數組不合適笙以。

我們想要自己id屬性和方法 。 要求這個一定是個對象才行冻辩。

1/聲明對象

我們有兩種聲明對象的方式.

var obj = new Object();    

但是我們更提倡用第二種方法: 字面量式聲明對象

 var obj  = {};

2/使用對象

聲明對象的完整源碼:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
</body>
</html>
<script>
    //   var obj = new Object();
    var obj = {};  // 聲明對象
    obj.name = "劉德華";  // 屬性
    obj.age = 55;
    obj.showName = function() {   // 聲明方法    方法一定帶有 ()
        alert("俺是劉德華");
    }
    obj.showAge = function() {
        alert("俺今年18歲");
    }
    console.log(obj.name);  // 調用屬性
    console.log(obj.age);
    obj.showName();   //  調用方法
    obj.showAge();
</script>

3/面向對象

面向對象里面:類和對象
類是對象的抽象猖腕,而對象是類的具體實例
一切事物皆對象 JavaScript 一切皆對象

類 和 對象

對象 女朋友
小胡 你有對象了嗎? 泛指 女朋友
旁邊坐的那個女生是你對象嗎恨闪? 特指 某一個女朋友
大家喜歡吃蘋果嗎倘感? 泛指 類
你手里的那個蘋果甜嗎? 特指 對象 (具體的實例)

面向對象的特性

-1. 抽象
抽象就是忽略一個主題中與當前目標無關的那些方面咙咽,以便更充分地注意與當前目標有關的方面老玛。
-2. 封裝
封裝是把過程和數據包圍起來,對數據的訪問只能通過已定義的界面
-3. 繼承
-4. 多態(tài)
多態(tài)是指兩個或多個屬于不同類的對象钧敞,對于同一個消息(方法調用)作出不同響應的方式

4/new

新的 我們經常利用new 關鍵字 去聲明新的對象
javascript

new運算符的作用是創(chuàng)建一個對象實例蜡豹。這個對象可以是用戶自定義的,也可以是帶構造函數的一些系統(tǒng)自帶的對象溉苛。

new 關鍵字可以讓 this 指向新的對象

所謂"構造函數"镜廉,其實就是一個普通函數,但是內部使用了this變量愚战。對構造函數使用new運算符桨吊,就能生成實例威根,并且this變量會綁定在實例對象上。

new關鍵字來聲明:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
</body>
</html>
<script>
    function Person(name,age) {     // 構造函數 就是一個普通函數 為了和普通函數區(qū)別 第一個字母大寫
        this.name = name;
        this.age = age;
        this.showName = function() {
            alert("我的名字是" + name);
        }
        this.showAge = function() {
            alert("我的年齡是"+ age);
        }
    }
    var demo =  new Person("劉德華",18);
    var demo1 = new Person("劉德華",18);
    console.log(demo.name); // 提倡用調用
    console.log(demo["name"]);
    console.log(demo.age);
    // demo.showName();
   /* alert(demo.showName);
    alert(demo1.showName);*/
    alert(demo.showName == demo1.showName);

</script>

5/prototype

共同的 相同的 部分

主要解決:函數因為使用非常非常多视乐,重復執(zhí)行效率太低洛搀。

類.prototype.方法  = function() {}  具體格式

可以把那些不變的屬性和方法,直接定義在prototype對象上

使用方法:

類名.prototype.方法

原型的面向對象:

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

</body>
</html>
<script>
   function Person(name,age) {   //  構造函數
       this.name = name;   // 只寫屬性
       this.age = age;
   }
    Person.prototype.showName = function() {  // 用的共同的父親
        alert("我的名字是"+ this.name);
    }
    Person.prototype.showAge = function() {
        alert("我的名字是"+ this.age);
    }
    var demo = new Person("劉德華",15);
    var demo1 = new Person("劉德華",15);
    demo.showName();
    alert(demo.showName === demo1.showName);
</script>

(面向對象版本)下拉菜單:

面向對象版本的下拉菜單.gif
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>無標題文檔</title>
<style type="text/css">
*{ padding:0; margin:0; list-style:none;}
.all{ width:330px; height:30px; background:url(img/bg.jpg) no-repeat; margin:100px auto; line-height:30px; text-align:center; padding-left:10px; margin-bottom:0;}
.all ul li{ width:100px; height:30px; background:url(img/libg.jpg); float:left; margin-right:10px; position:relative; cursor:pointer;}
.all ul ul{ position:absolute; left:0; top:30px; display:none;}
</style>
</head>

<body>
<div class="all" id="list">
    <ul>
        <li>一級菜單
            <ul>
                <li>二級菜單</li>
                <li>二級菜單</li>
                <li>二級菜單</li>
            </ul>
        </li>
        <li>一級菜單
            <ul>
                <li>二級菜單</li>
                <li>二級菜單</li>
                <li>二級菜單</li>
            </ul>
        </li>
        <li>一級菜單
            <ul>
                <li>二級菜單</li>
                <li>二級菜單</li>
                <li>二級菜單</li>
            </ul>
        </li>
    </ul>
</div>
</body>
</html>
<script>
    // 獲取對象     遍歷對象操作     顯示模塊   隱藏模塊

    function List(id) {  //  獲取對象
        this.id = document.getElementById(id);  // 取 id 值
        this.lis = this.id.children[0].children;  // 獲取一級菜單所有的li
    }
    // init 初始化
    List.prototype.init = function() {  // 遍歷所有的li 顯示和隱藏
        var that  = this;
        for(var i=0;i<this.lis.length;i++)
        {
            this.lis[i].index = i;
            this.lis[i].onmouseover = function() {
                that.show(this.children[0]);  //  顯示出來
            }
            this.lis[i].onmouseout = function() {
                that.hide(this.children[0]);  // 隱藏起來
            }
        }
    }
    //  顯示模塊
    List.prototype.show = function(obj) {
        obj.style.display = "block";
    }
    // 隱藏模塊
    List.prototype.hide = function(obj) {
        obj.style.display = "none";
    }
    var list = new List("list");  // 實例化了一個對象 叫  list
    list.init();
</script>

下拉菜單的案例素材獲扔拥怼:
鏈接:http://pan.baidu.com/s/1slQw0uL 密碼:zvlt

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末留美,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子伸刃,更是在濱河造成了極大的恐慌谎砾,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件捧颅,死亡現場離奇詭異景图,居然都是意外死亡,警方通過查閱死者的電腦和手機碉哑,發(fā)現死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進店門挚币,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人扣典,你說我怎么就攤上這事妆毕。” “怎么了贮尖?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵笛粘,是天一觀的道長。 經常有香客問我湿硝,道長薪前,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任关斜,我火速辦了婚禮示括,結果婚禮上,老公的妹妹穿的比我還像新娘蚤吹。我一直安慰自己例诀,他們只是感情好随抠,可當我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布裁着。 她就那樣靜靜地躺著,像睡著了一般拱她。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上秉沼,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天桶雀,我揣著相機與錄音矿酵,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的百匆。 我是一名探鬼主播宙彪,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤症虑,失蹤者是張志新(化名)和其女友劉穎主籍,沒想到半個月后千元,有當地人在樹林里發(fā)現了一具尸體涕烧,經...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡溢谤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年蛛壳,在試婚紗的時候發(fā)現自己被綠了衙荐。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片溜族。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡耳奕,死狀恐怖,靈堂內的尸體忽然破棺而出邪乍,到底是詐尸還是另有隱情榜配,我是刑警寧澤睛驳,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布匙瘪,位于F島的核電站驻啤,受9級特大地震影響骑冗,放射性物質發(fā)生泄漏遥倦。R本人自食惡果不足惜缩筛,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一桐臊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧识藤,春花似錦舌镶、人聲如沸餐胀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽炬丸。三九已至咪啡,卻和暖如春衫嵌,著一層夾襖步出監(jiān)牢的瞬間墓律,已是汗流浹背察纯。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工膊畴, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人滋尉。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓政勃,卻偏偏與公主長得像,于是被迫代替她去往敵國和親兼砖。 傳聞我的和親對象是個殘疾皇子奸远,可洞房花燭夜當晚...
    茶點故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內容

  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法讽挟,內部類的語法懒叛,繼承相關的語法,異常的語法耽梅,線程的語...
    子非魚_t_閱讀 31,598評論 18 399
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理薛窥,服務發(fā)現,斷路器眼姐,智...
    卡卡羅2017閱讀 134,628評論 18 139
  • 車水馬龍中诅迷,川流不息里,觥籌交錯間众旗,來來回回多的是孤獨的靈魂罢杉。《西雅圖》中說過:" 人生而孤獨贡歧,這就是世界滩租。在我眼...
    甘肅小女孩閱讀 468評論 0 1
  • 2016年可以說是耽美劇盛行的一年赋秀,大家看到了該類型的市場,為了分一杯羹律想,大大小小的制作方都開始磨刀霍霍的...
    謝小糊閱讀 107,073評論 7 20
  • 安裝報表 東臺bbu搬遷材料流程查詢 添加東臺bbu搬遷材料流程 查基站
    你好O楊紅閱讀 243評論 0 0