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

2017-03-18  本文已影响0人  Ainy尘世繁花终凋落

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

1.作用域变量搜索规则

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

总结作用域的画法:

作用域:

  1. 全局作用域
  2. 函数作用域

作用域的访问规则:

对象:实例属性|方法 原型属性|方法
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的值:

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.闭包的作用

闭包的作用:

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和闭包的执行

定时器:

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

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的主要任务(顺序):

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. 函数可以有自己的方法和属性

函数的创建方法:

注意:函数有名称: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. 函数是第一型对象(因此可以使用对象的地方都可以使用函数)
  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.自定义函数(惰性函数)

惰性函数定义:

注意点:

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]:

即时函数组成:

其他的写法:! + _ ~

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

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>

即时对象初始化

写法:

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. 设计模式:

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

2.工厂模式的说明

核心过程:

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>
上一篇下一篇

猜你喜欢

热点阅读