美文网首页html5从零开始学前端今日看点
前端基本功:JS(十三)闭包、面向对象

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

作者: 越IT | 来源:发表于2016-11-30 23:56 被阅读381次

    函数的复习:

    • 自定义函数和调用函数
    <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>
    

    闭包

    在程序语言中,所谓闭包,是指语法域位于某个特定的区域,具有持续参照(读写)位于该区域内自身范围之外的执行域上的非持久型变量值能力的段落。这些外部执行域的非持久型变量神奇地保留他们在闭包最初定义(或创建)时的值。

    白话: 我们可以用一个函数 去访问 另外一个函数的内部变量的方式就是闭包。

    内部变量 是 局部变量 那我们知道,局部变量是不可以为别人随便使用也。

    闭包原理 变量的作用链域

    闭包常用写法★★★★★

    <!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;   // !!核心!! 这里无括号即 返回的是 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

    这些外部执行域的非持久型变量神奇地保留他们在闭包最初定义(或创建)时的值。

    闭包的优缺点 :

    优点:不产生全局变量,实现属性私有化。
    缺点:闭包中的数据会常驻内存,在不用的时候要删掉否则会导致内存溢出。

    闭包原理★★★★★

    <script>
        function outFun() {
            var num = 10;
            function inFun() {   //  内部的函数可以使用外部的函数 变量
                console.log(num);
            }
            return inFun;  // 注意:不带括号!!不带括号返回函数体,带括号返回函数值
        }
        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.jianshu.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栏(闭包节流)

    <!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 等浏览器 每触发一次 ,执行两次
            num++;
           demo.innerHTML = window.innerWidth || document.documentElement.clientWidth;  // 得到当前的屏幕宽度
            console.log(num);
        }
    </script>
    

    (闭包版的函数节流):

    <!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) {  // 闭包  节流
             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. 多态
    多态是指两个或多个属于不同类的对象,对于同一个消息(方法调用)作出不同响应的方式

    4/new

    新的 我们经常利用new 关键字 去声明新的对象
    javascript

    new运算符的作用是创建一个对象实例。这个对象可以是用户自定义的,也可以是带构造函数的一些系统自带的对象。

    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) {     // 构造函数 就是一个普通函数 为了和普通函数区别 第一个字母大写
            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

    共同的 相同的 部分

    主要解决:函数因为使用非常非常多,重复执行效率太低。

    类.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

    相关文章

      网友评论

      本文标题:前端基本功:JS(十三)闭包、面向对象

      本文链接:https://www.haomeiwen.com/subject/dtggpttx.html