面向对象之闭包及设计模式的简单介绍day06

闭包及设计模式的简单介绍

1.作用域变量搜索规则

在函数内部声明变量不会覆盖上一层作用域中同名的变量

总结作用域的画法:

  • (1) 先画出0及级作用域链

    001 先找出有哪些全局的变量 a f1 f2 b
    002 连线(箭头 同级别的变量互相访问)

  • (2) 画出1级作用域链

    001 找函数 f1 延伸出一条线

    002 再在这条线上面画出当前函数内部的所有变量

  • (3) 重复第二个步骤

作用域:

  1. 全局作用域
  2. 函数作用域
  • 在代码中函数可以创建作用域
  • 函数内部又可以声明函数,创建了新的作用域
  • 函数内部的函数内部又可以声明函数

作用域的访问规则:

  • 01 先在自己的作用域中查找,如果找不到那么就去上一级查找
  • 02 在外部作用域中不能访问函数内部作用域

对象:实例属性|方法 原型属性|方法
obj.name

eg:

<script>
var a = 'testA';
function f1(){

    function f3(){
        var c = 'testC';
    }
}

function f2(){

}
var b = 'testB';
</script>
<script>
var a = 'testA';
function test1(){
    var a ;
    console.log(a);//undefined
    a = 20;
    console.log(a);//20
}
console.log(a);//testA
test1();//undefined  20
console.log(a);//testA
</script>

图形解析:


作用域链的图解

eg:图为上图:

<script>
    var a = "testA";
    function f1() {
        var b = "testB";
        function f2() {
            var i ;
            var k ;
        }
    }
    function f3() {
        var c = "testC";
        function f4() {
            var d = "testD";
        }
        function f5() {

        }
        var e = "e"
    }

</script>

2.闭包的简单介绍

闭包: 封闭+包裹

解决问题:
延长变量的生命周期 (变量创建-销毁)
提供一种间接访问函数封闭空间内部数据的方法.

需求: 需要获取a的值:

  • 01 直接返回就可以了? 解决不了.一次性的数据,如果调用多次函数返回的其实并不是同一个数据 +不能修改(设置)变量的值
  • 02 闭包解决 (把要访问的数据使用函数包裹返回)

eg:

<script>
function test(){
    var a= 10;
    return a;
}

var x = test();
console.log(x);
var y = test();//10
console.log(y);
</script>
<script>
function test(){
    var obj = {};
    return obj;
}
var x = test();
var y = test();
console.log(x == y);//false
</script>

3.闭包获取数据以及闭包设置数据

eg:

<script>
function test(){
    var a = 10;
    return function (value){
        if(value != undefined){
            a = value;
        }
        return a;
    }
}

var func = test();
console.log(func(30));//30
</script>

闭包如何获取函数内部的多个数据?

解决方案01

<script>
function test(){
    var name = '张三';
    var age = 88;
    var bookName = '未知书';

    return function (){
        return [name,age,bookName];
    }
}

var func = test();
console.log(func()[0]);
console.log(func()[1]);
console.log(func()[2]);
</script>

解决方案2

<script>
function test(){
    var name = '张三';
    var age = 88;
    var bookName = '未知书';

    return [function (){
        return name;
    },function (){
        return age;
    },function (){
        return bookName;
    }]
}

var func = test();
console.log(func[0]());
console.log(func[1]());
console.log(func[2]());
</script>

解决方案3

<script>
function test(){
    var name = '张三';
    var age = 88;
    var bookName = '未知书';

    return {
        getName:function (){
        return name;
    },
        getAge:function (){
        return age;
    },
        getBookName:function (){
        return bookName;
    },
        setName:function (nameValue){
            name = nameValue;
        },
        setAge:function (ageValue){
            age = ageValue;
        },
        setBookName:function (bookNameValue){
            bookName = bookNameValue;
        }
    }
}
console.log('_________________');
var func = test();
console.log(func.getName());
console.log(func.getAge());
console.log(func.getBookName());

//设置数据
func.setName('鲁迅');
func.setAge('20');
func.setBookName('骆驼祥子');
console.log(func.getName());
console.log(func.getAge());
console.log(func.getBookName());
</script>

4.闭包的作用

闭包的作用:

  • 01 提供一种间接访问(读写)函数内部封闭空间中数据的方法
  • 02 延长变量的生命周期
  • 03 保护数据让代码干呢更加安全和稳定 有时候在设置数据之前需要校验数据

eg:

<script>
function foo(){
    var age = 0;
    return {
        getAge:function (){
            return age;
        },
        setAge:function (aT){//校验数据
            if(aT<0){
                aT = 0;
            }
            age = aT;
        }
    }
}

var test = foo();
test.setAge(-20);
console.log(test.getAge());//0
</script>

5.setTimeout和闭包的执行

定时器:

  • setTimeout :一次定时器 ,只会执行一次(延迟执行函数)

参数:第一个参数:要执行的任务 ,第二个参数:间隔时间(单位毫秒 1000ms = 1s)

  • setInterval 每隔固定的时间就执行一次

eg:

 <script>
    var now = new Date();
    console.log(now);
    setTimeout(function(){
        console.log('一次定时器',new Date());
    },1000);
</script>
<script>
    var now = new Date();
    console.log(now);
    setInterval(function(){
        console.log('多次定时器',new Date());
    },1000);
</script>

6.线程与进程等相关概念

队列: 先进先出
栈:先进后出(数据结构 存储结构)

进程: 系统中正在运行的一个应用程序

线程: 是在进程中真正执行任务的部分.一个进程中至少有一条线程,可以有多个线程;
eg:学校-老师

串行执行:一条线程执行多个任务,在执行的时候按照固定的顺序一个接着一个的执行

并发执行:多条线程一起执行多个任务,同一个时间有多个任务在同时执行

多线程:
进程中可以有多条线程
优点:速度快,效率高 缺点:安全性差

主线程: 在进行开启的时候默认会创建一条线程,是主线程

并行和并发的区别:

并发: 多条线程同时执行任务的现象

并行: 同时执行多个任务的能力;

js本身是单线程

局限性: 如果要执行多个任务,只能串行的执行任务

js的主要任务(顺序):

  • 01 渲染任务
  • 02 脚本中的主要代码
  • 03 事件处理任务(定时器事件|点击事件等等)

eg:

<script>
for(var i= 0;i<10;i++){
    //执行定时器打印
  /*  (function (j){
        setTimeout(function (){
            console.log(j);
        },0)
    })(i);*/
    setTimeout((function (j){
        return function (){
            console.log(j);
        }
    })(i),0)
}
</script>

7.闭包在点击事件的应用

eg:
<body>
<div>我是第1个div</div>
<div>我是第2个div</div>
<div>我是第3个div</div>
<div>我是第4个div</div>
<div>我是第5个div</div>
<div>我是第6个div</div>
<div>我是第7个div</div>
<div>我是第8个div</div>
<div>我是第9个div</div>
<div>我是第10个div</div>
<script>
    var divs = document.getElementsByTagName('div');
    for(var i = 0;i<divs.length;i++){
        var div = divs[i];
       /* (function (j){
            div.onclick = function (){
                alert('我是第'+j+'个标签');
            }
        })(i);*/

        div.onclick = (function (j){
            return function (){
                alert('我是第'+j+'个标签');
            }
        })(i);
    }
</script>
</body

8.函数的特殊性

函数: 可以被调用()

  1. 本质是一个对象,因此凡是可以使用对象的地方都可以使用函数,函数可以作为其他函数的参数,也可以作为其他函数的返回值
  2. 函数可以创建作用域
  3. 函数可以有自己的方法和属性

函数的创建方法:

  • 01 函数声明 function 函数名(参数){函数体}

  • 02 表达式

    01 var func = function (){} 匿名的函数表达式

    02 var func = function name(){} 命名函数表达式

  • 03 构造函数 var func = new Function()

注意:函数有名称:name属性

eg:

<script>
var func01 = function (){};
var func02 = function funcName(){};

//注意:函数有名称:name属性
console.log(func01.name);//func01 注意:在火狐浏览器中为空
console.log(func02.name);//funcName
</script>

9.函数的回调(作为参数的传递)

  1. 函数作为其他函数的参数

回调: 回过头来调用

  1. 函数是第一型对象(因此可以使用对象的地方都可以使用函数)
  • 01 函数可以作为函数的参数
  • 02 函数可以作为函数的返回值
  1. 回调函数(回调),当我们把某个参数传递给另一个函数的时候,这个函数就称为回调函数

     eg:
     <script>
         function demo(callBack){
         //其他代码
             callBack();
         };
         function foo(){
             console.log('foo!');
         }
         demo(foo);//foo!
     </script>
    

分析代码:

原因: 函数调用方式改变

解决: call | apply

eg:

<script>
    var name = '我是测试代码';
    function demo(callBack){
        callBack();//使用回调函数
    }
    function func(){
        var name  = '张三';
        console.log('只是一个回调函数'  + this.name);
    }
    //注意点:window 有一个属性为name,并且为空.
    /*console.log(window.name);*/

    demo(func);//只是一个回调函数 我是测试代码



</script>
<script>
    //如果回调函数是某个对象的方法,而该对象方法中使用了this指针,那么该方法作为回调函数来使用的时候,需要注意this
    var name = '我是测试代码';
    function demo(callBack,callBackObj){
        //判断
        if(typeof callBack == 'string'){//字符串
            callBack = callBackObj[callBack];
        }
        if(typeof callBack == 'function'){//函数
            callBack.call(callBackObj);//借用callBack的方法
        }
        //其他代码
    }

var obj = {
    name:'张三',
    show:function (){
        console.log('show'+ this.name);
    }
};

var o = {
    name:'李四',
    show:function (){
        console.log('show'+ this.name);
    }
};

obj.show();
demo(obj.show,obj);//show 张三
demo(o.show,o);
demo('show',o);
demo('show',obj);

</script>

10.函数作为返回值

eg:
//使用闭包实现一个计数器(在该实例中)
//通过调用返回值(一个函数)

<script>
    function countF(){
        var count = 0;
        return function (){
            return count++;
        }
    }
    var next = countF();
    console.log(next());
    console.log(next());
    console.log(next());
    console.log(next());
    console.log(next());
    console.log(next());
</script>

11.自定义函数(惰性函数)

惰性函数定义:

  • 特点是在第二次调用函数的时候这个函数才被正确的定义;第一次调用函数的时候只是做了一些初始化的处理
  • 特征:可以实现函数的自我更新

注意点:

  • 01 实现自我更新之后函数上面的属性会丢失
  • 02 把函数赋值给变量或者是对象的方法之后,以变量或者是对象的方法来调用函数的时候,不会实现自我更新

eg:

<script>
function foo(){
    console.log('foo!');
    //初始化操作

    foo = function (){
        console.log('foo!','foo!');
    }
}
foo.des = 'foo的描述信息';
   /* foo();//foo!
    foo();//foo! foo!
    foo();//foo! foo!*/
    console.log(foo.des);//undefined

var demo = foo;
var obj = {};
obj.show = foo;
demo();//foo!
demo();//foo!
demo();//foo!
console.log('+++++++++++');
foo();//foo! foo!
obj.show();//foo!
obj.show();//foo!
obj.show();//foo!
</script>

12.即时函数的补充以及初始化

基本写法[2]:

即时函数组成:

  • 001 函数(函数体 + function + 参数 + 返回值)
  • 002 ()包住函数
  • 003 ()调用函数

其他的写法:! + _ ~

即时函数可以接受参数也可以返回数据

eg:

<script>
//01第一种写法
/*(function (){
    console.log('第一种写法');
})()

//02第二种写法
(function (){
    console.log('第二种写法');
}())

//03 其他写法
!(function (){
    console.log('不建议的演示');
})();

+(function (){
    console.log('不建议的演示');
})();

-(function (){
    console.log('不建议的演示');
})();

~(function (){
    console.log('不建议的演示');
})();*/

var result = (function (string){
    var str = 'hello'+ string;
    console.log(str);
    return str;
})('demo');
console.log(result);
</script>

即时对象初始化

写法:

  • 01 提供一个对象{}属性和方法
  • 02 在对象中提供一个初始化的方法,主要做一些初始化操作
  • 03 在对象外部添加(),包装成一个表达式
  • 04 直接使用.init()来进行初始化处理

eg:

<script>
({
    name:'张三',
    age:99,
    showName:function (){
        console.log(this.name);
    },
    showAge:function (){
        console.log(this.age);
    },
    init:function (){
        //初始化处理
        this.showName();
        this.showAge();
    }
}).init();
console.log(name);//空
console.log(age);//报错

#### 二.设计模式的简单介绍

1. 设计模式:

  • 设计模式本身是一种解决特定问题的套路
  • 设计模式的分类:23种
  • 设计模式的来源于建筑学邻域
  • 设计模式的由来:四人帮(设计模式)

列举:单利模式 | 代理模式 |观察者模式 |工厂模式 | 策略模式 | 桥接模式 ......

2.工厂模式的说明

核心过程:

  • 01 提供父构造函数
  • 02 设置父构造函数的原型对象(属性|方法) 目的的共享
  • 03 为父构造函数提供一个静态工厂方法(每次要生产产品就调用这个方法)
    1. 001 接收产品的类型
    2. 002 判断是否支持生产该类型的产品
    3. 003 设置原型继承,获得原型对象上面的方法
    4. 004 生产该类型的一个产品
    5. 005 返回对象
  • 04 定制合作伙伴(子构造函数)
  • 05 调用父构造函数的工厂函数来创建对象

eg:

<script>
    //01 提供父构造函数
    function MakePhone(){};
    //02 设置父构造函数的原型对象(属性|方法)  目的的共享
    MakePhone.prototype.desLog = function (){
        console.log('我的广告是:' + this.des);
    };

    //03 为父构造函数提供一个静态工厂方法(每次要生产产品就调用这个方法)
    MakePhone.factory = function (stringType){
        //001 接收产品的类型
        var phoneType = stringType;
        if(phoneType == undefined){
            throw '请下订单';
        }
        //002 判断是否支持生产该类型的产品
        if(typeof MakePhone[phoneType] != 'function'){
            throw '和该品牌没有任何的合作关系,不支持生产';
        };
        //003 设置原型继承,获得原型对象上面的方法
        MakePhone[phoneType].prototype = MakePhone.prototype;
        //004 生产该类型的一个产品
        var newPhone = new MakePhone[phoneType]();

        //005返回对象
        return newPhone;

    };
    //04 定制合作伙伴(子构造函数)
    MakePhone.iphone = function (){
        this.des = '最贵的手机,最垃圾的系统';
    };
    MakePhone.vivo = function (){
        this.des = '充电五分钟,通话两小时';
    };
    MakePhone.oppo = function (){
        this.des = '照亮你的美';
    };
    //05调用父构造函数的工厂函数来创建对象
    var iphone = MakePhone.factory('iphone');
    iphone.desLog();
    var oppo = MakePhone.factory('oppo');
    oppo.desLog();
    var vivo = MakePhone.factory('vivo');
    vivo.desLog();
    </script>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容