15_JS閉包倦淀、對象蒋畜、原型

閉包

在程序語言中,所謂閉包晃听,是指語法域位于某個特定的區(qū)域百侧,具有持續(xù)參照(讀寫)位于該區(qū)域內(nèi)自身范圍之外的執(zhí)行域上的非持久型變量值能力的段落砰识。這些外部執(zhí)行域的非持久型變量神奇地保留他們在閉包最初定義(或創(chuàng)建)時的值能扒。
  白話: 我們可以用一個函數(shù) 去訪問 另外一個函數(shù)的內(nèi)部變量的方式就是閉包。

  • 變量作用域
function outFun() {
        var num = 10;  //  outFun 的一個變量
        function inFun() {
            var key = 10;
            console.log(num);  //   外部函數(shù)的變量可以被內(nèi)部函數(shù)所使用
        }
        console.log(key);    // 這樣是不可以的辫狼,內(nèi)部函數(shù)的變量不可以被外部函數(shù)所使用
    }
  • 閉包常用寫法
function outFun(){
        var num = 10;// 讓fun 函數(shù)以外的函數(shù) 的使用 num 的值  就可以創(chuàng)建閉包
        function inFun(){
            console.log(num);
        }
        return inFun;// 返回的是 inFun函數(shù)體  核心
}
//        使用
var demo = outFun();
console.log(demo);
demo();//輸出10初斑,這個10是另外一個函數(shù)的變量
  • 閉包練習(xí)
        function outerFun(){
            var a = 0;
            function innerFun(){
                a++;
                alert(a);
            }
            return innerFun;
        }
        var o1 = outerFun();
        o1();//1
        o1();//2

        var o2 = outerFun();
        o2();//1
        o2();//2
  • 簡寫
  function outerFun(){
            var a = 0;
            function innerFun(){
                a++;
                alert(a);
            }
            return innerFun;
        }

可以這樣簡寫

        function outerFun(){
            var a = 0;
            return function(){
                a++;
                alert(a);
            }
        }
  • 閉包傳參
        function outerFun(x){
            function innerFun(){
                console.log(x);
            }
            return innerFun;//不能帶括號
        }
        var obj = outerFun(4);
        obj();

        function outerFun(x){
            function innerFun(y){
                console.log(x+y);
            }
            return innerFun;//不能帶括號
        }
        var obj = outerFun(4);
        obj();//NaN
        obj(2);//6
  • **閉包的優(yōu)缺點(diǎn) : **
  • 優(yōu)點(diǎn):不產(chǎn)生全局變量,實(shí)現(xiàn)屬性私有化膨处。
  • 缺點(diǎn):閉包中的數(shù)據(jù)會常駐內(nèi)存见秤,在不用的時候要刪掉否則會導(dǎo)致內(nèi)存溢出。

例:閉包案例真椿,事件參數(shù)傳遞

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">
        .box{
            position: absolute;
            left: 0;
            width: 100px;
            height: 100px;
            background-color: red;
        }
    </style>
    <script type="text/javascript">
        window.onload = function () {
            var btn1 = document.getElementById("btn1");
            var btn2 = document.getElementById("btn2");
            var box = document.getElementById("box");
            //以前的傳統(tǒng)寫法
            /*
            var speed = 5;
            btn1.onclick = function () {
                box.style.left = box.offsetLeft+speed+"px";
            }
            btn2.onclick = function () {
                box.style.left = (box.offsetLeft-speed)+"px";
            }
            */
            //封裝函數(shù)的寫法
            /*
            btn1.onclick = function () {
                move(5);
            }
            btn2.onclick = function () {
                move(-5);
            }
            function move(speed){
                box.style.left = box.offsetLeft+speed+"px";
            }
            */
            //閉包傳遞參數(shù)的寫法
            function move(speed){
                return function () {
                    box.style.left = box.offsetLeft+speed+"px";
                }
            }
            btn1.onclick = move(5);
            btn2.onclick = move(-5);
        }
    </script>
</head>
<body>
    <button id="btn1">右走</button>
    <button id="btn2">左走</button>
    <div class="box" id="box"></div>
</body>
</html>

例:tab欄切換鹃答,使用閉包

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">
        body,ul,li{
            margin: 0;
            padding: 0;
        }
        ul,li{
            list-style: none;
        }
        .box{
            width: 500px;
            height: 430px;
            margin: 15px auto;
        }
        .tab-btn{
            width: 500px;
            height: 30px;
        }
        .tab-btn li{
            float: left;
            width: 100px;
            height: 30px;
            line-height: 30px;
            background-color: #ccc;
            color: #333;
            text-align: center;
        }
        .tab-btn .current{
            background-color: red;
            color:#fff;
        }
        .tab-con div{
            width: 500px;
            height: 400px;
            background-color: red;
            display: none;
        }
        .tab-con .show{
            display: block;
        }
    </style>
    <script type="text/javascript">
        window.onload = function () {
            function $(id){return document.getElementById(id);}
            function tab(id){
                var lis = $(id).getElementsByTagName("li");
                var cons = $(id).getElementsByClassName("tab-con")[0].getElementsByTagName("div");
                for(var i=0; i<lis.length; i++){
                    lis[i].index = i;
                    lis[i].onmouseover = tab(i);
                }

                //使用了閉包
                function tab(num){
                    return function () {
                        for(var j=0; j<lis.length; j++){//清除所有
                            lis[j].className = "";
                            cons[j].className = "";
                        }
                        lis[num].className = "current";//留下當(dāng)前的
                        cons[num].className = "show";
                    }
                }
            }
            tab("one");//第一個tab欄
            tab("two");//第二個tab欄
        }
    </script>
</head>
<body>
<div class="box" id="one">
    <div class="tab-btn">
        <ul>
            <li class="current">首頁</li>
            <li>新聞時事</li>
            <li>體育</li>
            <li>購物</li>
            <li>游戲</li>
        </ul>
    </div>
    <div class="tab-con">
        <div class="show">首頁</div>
        <div>新聞時事</div>
        <div>體育</div>
        <div>購物</div>
        <div>游戲</div>
    </div>
</div>
<div class="box" id="two">
    <div class="tab-btn">
        <ul>
            <li class="current">首頁</li>
            <li>新聞時事</li>
            <li>體育</li>
            <li>購物</li>
            <li>游戲</li>
        </ul>
    </div>
    <div class="tab-con">
        <div class="show">首頁</div>
        <div>新聞時事</div>
        <div>體育</div>
        <div>購物</div>
        <div>游戲</div>
    </div>
</div>
</body>
</html>

修改為閉包的立即執(zhí)行,修改之后

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">
        body,ul,li{
            margin: 0;
            padding: 0;
        }
        ul,li{
            list-style: none;
        }
        .box{
            width: 500px;
            height: 430px;
            margin: 15px auto;
        }
        .tab-btn{
            width: 500px;
            height: 30px;
        }
        .tab-btn li{
            float: left;
            width: 100px;
            height: 30px;
            line-height: 30px;
            background-color: #ccc;
            color: #333;
            text-align: center;
        }
        .tab-btn .current{
            background-color: red;
            color:#fff;
        }
        .tab-con div{
            width: 500px;
            height: 400px;
            background-color: red;
            display: none;
        }
        .tab-con .show{
            display: block;
        }
    </style>
    <script type="text/javascript">
        window.onload = function () {
            function $(id){return document.getElementById(id);}
            function tab(id){
                var lis = $(id).getElementsByTagName("li");
                var cons = $(id).getElementsByClassName("tab-con")[0].getElementsByTagName("div");
                for(var i=0; i<lis.length; i++){
                    lis[i].index = i;
                    lis[i].onmouseover = function(num){//閉包的立即執(zhí)行
                        return function () {
                            for(var j=0; j<lis.length; j++){//清除所有
                                lis[j].className = "";
                                cons[j].className = "";
                            }
                            lis[num].className = "current";//留下當(dāng)前的
                            cons[num].className = "show";
                        }
                    }(i);
                }
            }
            tab("one");//第一個tab欄
            tab("two");//第二個tab欄
        }
    </script>
</head>
<body>
<div class="box" id="one">
    <div class="tab-btn">
        <ul>
            <li class="current">首頁</li>
            <li>新聞時事</li>
            <li>體育</li>
            <li>購物</li>
            <li>游戲</li>
        </ul>
    </div>
    <div class="tab-con">
        <div class="show">首頁</div>
        <div>新聞時事</div>
        <div>體育</div>
        <div>購物</div>
        <div>游戲</div>
    </div>
</div>
<div class="box" id="two">
    <div class="tab-btn">
        <ul>
            <li class="current">首頁</li>
            <li>新聞時事</li>
            <li>體育</li>
            <li>購物</li>
            <li>游戲</li>
        </ul>
    </div>
    <div class="tab-con">
        <div class="show">首頁</div>
        <div>新聞時事</div>
        <div>體育</div>
        <div>購物</div>
        <div>游戲</div>
    </div>
</div>
</body>
</html>

tab欄切換添加函數(shù)節(jié)流

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">
        body,ul,li{
            margin: 0;
            padding: 0;
        }
        ul,li{
            list-style: none;
        }
        .box{
            width: 500px;
            height: 430px;
            margin: 15px auto;
        }
        .tab-btn{
            width: 500px;
            height: 30px;
        }
        .tab-btn li{
            float: left;
            width: 100px;
            height: 30px;
            line-height: 30px;
            background-color: #ccc;
            color: #333;
            text-align: center;
        }
        .tab-btn .current{
            background-color: red;
            color:#fff;
        }
        .tab-con div{
            width: 500px;
            height: 400px;
            background-color: red;
            display: none;
        }
        .tab-con .show{
            display: block;
        }
    </style>
    <script type="text/javascript">
        window.onload = function () {
            function $(id){return document.getElementById(id);}
            function tab(id){
                var lis = $(id).getElementsByTagName("li");
                var cons = $(id).getElementsByClassName("tab-con")[0].getElementsByTagName("div");
                for(var i=0; i<lis.length; i++){
                    lis[i].index = i;
                    var timer = null;
                    lis[i].onmouseover = function(num){//閉包的立即執(zhí)行+函數(shù)節(jié)流
                        return function () {
                            clearTimeout(timer);
                            timer = setTimeout(function () {
                                for(var j=0; j<lis.length; j++){//清除所有
                                    lis[j].className = "";
                                    cons[j].className = "";
                                }
                                lis[num].className = "current";//留下當(dāng)前的
                                cons[num].className = "show";
                            },300);
                        }
                    }(i);
                    lis[i].onmouseout = function () {
                        clearTimeout(timer);
                    }
                }
            }
            tab("one");//第一個tab欄
            tab("two");//第二個tab欄
        }
    </script>
</head>
<body>
<div class="box" id="one">
    <div class="tab-btn">
        <ul>
            <li class="current">首頁</li>
            <li>新聞時事</li>
            <li>體育</li>
            <li>購物</li>
            <li>游戲</li>
        </ul>
    </div>
    <div class="tab-con">
        <div class="show">首頁</div>
        <div>新聞時事</div>
        <div>體育</div>
        <div>購物</div>
        <div>游戲</div>
    </div>
</div>
<div class="box" id="two">
    <div class="tab-btn">
        <ul>
            <li class="current">首頁</li>
            <li>新聞時事</li>
            <li>體育</li>
            <li>購物</li>
            <li>游戲</li>
        </ul>
    </div>
    <div class="tab-con">
        <div class="show">首頁</div>
        <div>新聞時事</div>
        <div>體育</div>
        <div>購物</div>
        <div>游戲</div>
    </div>
</div>
</body>
</html>

例:立即執(zhí)行函數(shù)

<script type="text/javascript">
        var fun = function(){}
        //方式一
        fun();//立即執(zhí)行
        //方式二
        function(){}();//立即執(zhí)行
    </script>

案例:如上tab欄的修改之后

例:函數(shù)節(jié)流

        window.onload = function () {
            var box = document.getElementById("box");
            var num = 0;

            window.onresize = throttle(function () {
                num++;
                box.innerHTML = window.innerWidth||document.documentElement.clientWidth;
                console.log(num);
            },30);

            function throttle(fn,delay){//閉包,節(jié)流
                var timer = null;
                return function () {
                    clearInterval(timer);
                    timer = setTimeout(fn,delay);
                }
            }
        }

對象(object)

對象是什么突硝?
基本數(shù)據(jù)類型 :string number boolean null undefined
Array對象
對象數(shù)據(jù)類型: 對象就是帶有屬性和方法的數(shù)據(jù)類型

var num = 10;   // 變量
var arr = [];  // 數(shù)組
arr.index = 10;  // 數(shù)組arr 的 一個 index  屬性

但是有個問題测摔, 我們想要某些屬性或者方法的時候,用數(shù)組不合適。arr.lenght
我們想要自己id屬性和方法 锋八。 要求這個一定是個對象才行浙于。

聲明對象

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

var obj = new Object();

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

var obj = {};

var obj = {};  // 聲明對象
obj.name = "劉德華";  // 屬性
obj.age = 55;
obj.showName = function() {   // 聲明方法    方法一定帶有 ()
    alert("俺是劉德華");
}
obj.showAge = function() {
    alert("俺今年18歲");
}

使用對象

console.log(obj.name);  // 調(diào)用屬性
console.log(obj.age);
obj.showName();   //  調(diào)用方法
obj.showAge();

this


    <script type="text/javascript">
        function fn(){
            console.log(this);//this指向window對象
        }
        fn();

        function fn1(){
            this.x = 12;
        }
        fn1();
        console.log(window.x);//打印12

        new fn();//使用new的函數(shù),this指向新的對象挟纱,而不是window

        function person(){
            this.x = 20;
        }

        var demo = new person();
        console.log(demo.x);//打印20
        console.log(window.x);//打印12
    </script>

new

我們經(jīng)常利用new 關(guān)鍵字 去聲明新的對象
  new運(yùn)算符的作用是創(chuàng)建一個對象實(shí)例羞酗。這個對象可以是用戶自定義的,也可以是帶構(gòu)造函數(shù)的一些系統(tǒng)自帶的對象紊服。
  new 關(guān)鍵字可以讓 this 指向新的對象
  所謂"構(gòu)造函數(shù)"檀轨,其實(shí)就是一個普通函數(shù),但是內(nèi)部使用了this變量欺嗤。對構(gòu)造函數(shù)使用new運(yùn)算符裤园,就能生成實(shí)例,并且this變量會綁定在實(shí)例對象上剂府。

prototype

共同的 相同的 部分
主要解決:函數(shù)因?yàn)槭褂梅浅7浅6嗯±浚貜?fù)執(zhí)行效率太低。

Person.prototype.showName = function() {  // 用的共同的父親
    alert("我的名字是"+ this.name);
}

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

可以把那些不變的屬性和方法腺占,直接定義在prototype對象上
使用方法:類名.prototype.方法

<script type="text/javascript">
        Array.prototype.run = function () {
            console.log(this);
            console.log(this.length);
        }
        var demo1 = [1,2,3,5];
        demo1.run();

        var demo2 = [5];
        demo2.run();
    </script>

        function Person(name,age){
            this.name = name;
            this.age = age;
        }
        Person.prototype.showName = function () {
            alert("名稱="+this.name);
        }
        var p1 = new Person("劉德華",24);
        var p2 = new Person("張學(xué)友",23);
        p1.showAge = function () {
            alert("年齡="+this.age);
        }
        p2.showAge = function () {
            alert("年齡="+this.age);
        }

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

上面第一個打印false淤袜,第二個打印true,第三個打印true

例:下拉菜單衰伯,面向?qū)ο蟀?/p>

<!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>無標(biāo)題文檔</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");  // 實(shí)例化了一個對象 叫  list
    list.init();
</script>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末铡羡,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子意鲸,更是在濱河造成了極大的恐慌烦周,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,496評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件怎顾,死亡現(xiàn)場離奇詭異读慎,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)槐雾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,187評論 3 385
  • 文/潘曉璐 我一進(jìn)店門夭委,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人募强,你說我怎么就攤上這事株灸。” “怎么了擎值?”我有些...
    開封第一講書人閱讀 157,091評論 0 348
  • 文/不壞的土叔 我叫張陵慌烧,是天一觀的道長。 經(jīng)常有香客問我鸠儿,道長屹蚊,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,458評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮淑翼,結(jié)果婚禮上腐巢,老公的妹妹穿的比我還像新娘。我一直安慰自己玄括,他們只是感情好冯丙,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,542評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著遭京,像睡著了一般胃惜。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上哪雕,一...
    開封第一講書人閱讀 49,802評論 1 290
  • 那天船殉,我揣著相機(jī)與錄音,去河邊找鬼斯嚎。 笑死利虫,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的堡僻。 我是一名探鬼主播糠惫,決...
    沈念sama閱讀 38,945評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼钉疫!你這毒婦竟也來了硼讽?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,709評論 0 266
  • 序言:老撾萬榮一對情侶失蹤牲阁,失蹤者是張志新(化名)和其女友劉穎固阁,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體城菊,經(jīng)...
    沈念sama閱讀 44,158評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡备燃,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,502評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了役电。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赚爵。...
    茶點(diǎn)故事閱讀 38,637評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖法瑟,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情唁奢,我是刑警寧澤霎挟,帶...
    沈念sama閱讀 34,300評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站麻掸,受9級特大地震影響酥夭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,911評論 3 313
  • 文/蒙蒙 一熬北、第九天 我趴在偏房一處隱蔽的房頂上張望疙描。 院中可真熱鬧,春花似錦讶隐、人聲如沸起胰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,744評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽效五。三九已至,卻和暖如春炉峰,著一層夾襖步出監(jiān)牢的瞬間畏妖,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,982評論 1 266
  • 我被黑心中介騙來泰國打工疼阔, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留戒劫,地道東北人。 一個月前我還...
    沈念sama閱讀 46,344評論 2 360
  • 正文 我出身青樓婆廊,卻偏偏與公主長得像谱仪,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子否彩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,500評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 王福朋 - 博客園 —— 《 深入理解javascript原型和閉包》 目錄:深入理解javascript原型和閉...
    帥而不花__美而不浪閱讀 1,432評論 0 2
  • 繼承 一疯攒、混入式繼承 二、原型繼承 利用原型中的成員可以被和其相關(guān)的對象共享這一特性列荔,可以實(shí)現(xiàn)繼承敬尺,這種實(shí)現(xiàn)繼承的...
    magic_pill閱讀 1,054評論 0 3
  • 1.對象是什么 對象就是若干屬性的集合。 在JS中一切引用類型都是對象:數(shù)組是對象贴浙,函數(shù)是對象砂吞,對象還是對象。對象...
    liushaung閱讀 1,205評論 0 2
  • 1 看書 昨天因?yàn)槌蕴鞘乱?沒有達(dá)成共同意見 閨女不高興 我也沒有哄 自己找到調(diào)試辦法 打開比巴 可是不會播放 也...
    瑩瑩生輝閱讀 264評論 0 0
  • 晚上給兒子洗澡崎溃。 浩寶問:“媽媽蜻直,你的浩寶會做做很多事情嗎?你的浩寶乖嗎袁串?”
    小滿李閱讀 136評論 0 0