js设计模式(四)单例模式、策略模式、new function()和function()有什么区别、js中奇特的for循环写法、代理模式

一、单例模式

定义:保证一个类只有一个实例,并提供一个访问它的全局访问点

有一些对象我们往往只需要一个,比如登陆浮窗

let createIframe = (function(){
    let iframe 
    return function(){
        if(!iframe){
    
        }
        return iframe
    }

})()

将变与不变的隔离出来,逻辑始终是:用一个变量标志是否创建过对象,如果是,则在下次直接返回这个已经创建好的对象

二、策略模式

定义:定义一系列的算法,把它们一个个封装起来,并且使他们可以互相替换

比如表单验证,普通的表单验证缺点

Ⅰ函数庞大,包含很多if-else语句

Ⅱ函数缺乏弹性,如果增加了一种新的校验规则,必须深入函数内部实现,违反开放-封闭原则

Ⅲ算法的复用性差,如果在程序中增加了另一个表单,这个表单也需要一些类似的校验,那我很可能将这些校验

       function test(){
            let strategies = { //将校验逻辑封装成策略模式
                isNonEmpty:function(value,errorMsg){
                    if(value === ''){
                        return errorMsg
                    }
                },
                minLength:function(value,length,errorMsg){
                    if(value.length<length){
                        return errorMsg
                    }
                }
            }
            //校验类
            let Validator = function(){
                this.cache = []//保存校验规则
            }
            Validator.prototype.add = function(dom,rule,errorMsg){
                let arr = rule.split(':')//把strategy和参数分开
                this.cache.push(()=>{
                    let strategy = arr.shift() //获取要验证的校验逻辑
                    arr.unshift(dom.value)  //添加要验证的值
                    arr.push(errorMsg)   //将errmsg添加进参数列表
                    return strategies[strategy].apply(dom,arr)
                })
            }
            Validator.prototype.start = function(){    //
                for(let i = 0,validator;validator=this.cache[i++];){
                    let msg = validator()  //开始校验规则
                    if(msg){ //若返回消息说明错误
                        return msg 
                    }
                }
            }

            let validatorFunc = function(){
                let validator = new Validator()
                validator.add(document.getElementById('test'),'isNonEmpty','用户名不能为空')

                let errorMsg = validator.start() //获得校验结果
                console.log(errorMsg)
                return errorMsg
            }
        }

 

 

3、js中奇特的for循环写法

//正常的for循环
for(var i=0;i<10;i++){
console.log(i);
}
//输出:1,2,3……10


//简写
for(var i=10;i--;){
console.log(i);
}
//输出:9,8,7,……0

//变种:
for(var i=-10;i++;){
console.log(i*-1);
}
//输出:9,8,7,……0
因为在js中,0,null,undefined,false,'',""作为条件判断时,其结果为false

if(0)相当于if(false)

if(!0)相当于if(true)

 

for终止循环时是这样的

for(var i=10;0;){}

 

4、new function()和function()有什么区别

new做了三件事:

var instance = {};
instance.__proto__ = ShowUsers.prototype;
ShowUsers.call(obj);

简单来说,它改变了内部this的指向(不适用new时,this指向全局window or global),还有继承了原型链

5、代理模式

定义:为一个对象提供一个代用品或占位符,以便控制对它的访问

保护代理和虚拟代理

保护代理用于控制不同权限的对象对于目标对象的访问,但在js无法判断谁访问了某个对象

虚拟代理把一些开销很大的对象,延迟到真正需要它的时候才去创建

虚拟代理应用:

①通过代理对象在图片被加载好之前,页面中将出现一张占位的loading.gif,来提示用户图片正在加载

let myImage = (function (){
            let imgNode = document.createElement('img')
            document.body.append(imgNode)
            return {
                setSrc:function(src){
                    imgNode.src =src
                }
            }
        })()    
        let proxyImg = ()=>{
            let img = new Image
            img.onload = function(){
                myImage.setSrc(this.src)
            }
            return{
                setSrc:function(src){
                    myImage.setSrc('')
                    img.src = src
                }
            }
        }

如上通过proxyImage间接访问MyImage,proxyImage控制了客户对myImage的访问。并且在此过程中加入一些额外的操作。比如真正的图片加载之前,先把img节点的src设置为一张本地的loading图片

为什么一个小小的图片预加载功能要用到代理模式?,这就需要引入一面向对象设计的原则--单一职责原则

单一原则指的是,就一个类而言,应该仅有一个引起他变化的原因。            如果一个对象承担了多项原则,意味着这个对象将变得巨大,引起他变化的原因可能有多个。

②虚拟代理合并HTTP请求

在web开发中,也许最大的开销就是网络请求。解决方案是,通过一个代理函数proxySysnchronousFile来手机一段时间之内的请求,最后一次性发送给服务器(如果不是对实时性要求非常高的系统,1s/2s的延迟不会带来太大副作用,却能大大减轻服务器的压力)

let proxySysnchronousFile = function(id){
            let cache = []
            let timer
            return function(id){
                cache.push(id)//保存请求
                if(timer){
                    return
                }
                timer = setTimeout(()=>{
                    //发送请求
                    clearTimeout(timer)
                    timer = null
                    cache.length = 0
                },2000)
            }
        }

5.2、缓存代理

缓存代理可以为一些开销大的运算结果提供暂时的存储,在下次运算时如果传递进来的参数跟之前一致,则可以直接返回前面存储的运算结果。

缓存代理用于ajax异步请求数据

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值