前端基本功: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>

闭包

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

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

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

闭包原理
变量的作用链域

闭包常用写法★★★★★

<!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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,829评论 1 331
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,603评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,846评论 0 226
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,600评论 0 191
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,780评论 3 272
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,695评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,136评论 2 293
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,862评论 0 182
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,453评论 0 229
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,942评论 2 233
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,347评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,790评论 2 236
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,293评论 3 221
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,839评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,448评论 0 181
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,564评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,623评论 2 249

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,275评论 18 399
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,050评论 18 139
  • 车水马龙中,川流不息里,觥筹交错间,来来回回多的是孤独的灵魂。《西雅图》中说过:" 人生而孤独,这就是世界。在我眼...
    甘肃小女孩阅读 449评论 0 1
  • 2016年可以说是耽美剧盛行的一年,大家看到了该类型的市场,为了分一杯羹,大大小小的制作方都开始磨刀霍霍的...
    谢小糊阅读 106,491评论 7 20
  • 安装报表 东台bbu搬迁材料流程查询 添加东台bbu搬迁材料流程 查基站
    你好O杨红阅读 219评论 0 0