6

本回内容介绍

上一回,聊了门面模式,DOM2级事件,事件委托,介一回,也比较容易,代理模式(proxy),代理对象控制对本体对象的访问,实现了同样的接口,并且会把任何方法的调用传递到本体对象。
说白了,就是对访问进行控制。直接上代码,走你:

1.代理模式

代理也是对象,主要就是保护本体对象,对本体对象进行访问控制,本体对象有的,代理对象也有,如下:

// 定义一个房子的接口,可以租,可以卖,这里就只实现一个好了,保留租的方法:rent,有兴趣的可以扩展另一个
var House = new Interface("House",["sale"]);

// 买方
function Buyer(name){
    this.name = name;
}

// 中介,也就是代理,这里传递的对象是买方对象
var Proxy = function(o){
    // 买方名字
    this.buyer = o.name;
    // 业主实例
    if(this.owner==null){
        this.owner = new Owner(o);
    }
    // 验证接口
    Interface.ensureImplements(this,House);
};

// 代理对象对本体对象的方法实现
Proxy.prototype = {
    // 还原构造器
    constructor:Proxy,
    // 代理对象同样实现本体的方法
    sale:function(money){
        return this.owner.sale(money);
    }
};

// 业主即本体,传递的对象依然是买方对象
var Owner = function(o){
    this.buyer = o.name;
    Interface.ensureImplements(this,House);
};

// 本体对象的方法实现
Owner.prototype = {
    constructor:Owner,
    // 本体对象的方法
    sale:function(money){
        return this.buyer+'支付了'+money+'万元买了别墅.';
    }
};
var br = new Buyer('飞狐');
alert(new Proxy(br).sale('500'));    // 飞狐支付了500万元买了别墅. 

这个例子比较直观,买方,卖方,中介三种角色很好的诠释了代理模式,也比较好理解,看下一个例子,走你.

2. 虚拟代理

这里聊一个虚拟代理,就是在代理的方法被调用的时候再去实例化相关的对象。还记得之前的惰性单例模式么,虚拟代理有点类似,看例子:

// 定义一个年级
var Grades = function(){};

Grades.prototype = {
    // 检测人数
    check:function(o){
        alert(o.length+"人");
    }
}; 

// 年级代理
var GradesProxy = function() {
    // 先不初始化Grades.
    this.gra = null;
};

GradesProxy.prototype = {
    // 这里就是按需初始化
    init: function() {
        if (!this.gra) {
            this.gra = new Grades();
        }
    },
    // 检测学生人数
    check: function(s) {
        // 调用 init()
        this.init();
        return this.gra.check(s);
    }
}

// 测试
var students = ['大卫','撸壕','飞狐'];
var o = new GradesProxy();
o.check(students); //3人

这个例子比较简单,没有写太多方法,也没有单独写学生类,用一个数组一笔带过,目的是更直观的展示在用时初始化本体对象。

装逼图
惯例性装逼,今天看新闻,钟汉良导演,韩寒监制的新片《沙漏》,继《后会无期》后又一次合作,期待啊~~

这一回聊的内容少,难度很小,比较好理解。
下面的内容来一个实例,懒加载,懒加载是代理模式很好的一个实践。

JS图片懒加载

懒加载又叫延迟加载,通过自定义属性,把真实的img地址存到自定义属性中,如:data-url=”img”,而图片真正的src存的是loading的图片,如src=”loading.gif”,当拖动滚动条发生窗口的偏移,再动态将data-url的值赋给src; 实时的替换img的src的图片路径,绕么,看例子吧:

// 这里是html的代码,
<ul>
    <li><img src="./img/loading.gif" data-url="./img/1.jpg"/></li>
    <li><img src="./img/loading.gif" data-url="./img/2.jpg"/></li>
    <li><img src="./img/loading.gif" data-url="./img/3.jpg"/></li>
    <li><img src="./img/loading.gif" data-url="./img/4.jpg"/></li>
    <li><img src="./img/loading.gif" data-url="./img/5.jpg"/></li>
    <li><img src="./img/loading.gif" data-url="./img/6.jpg"/></li>
</ul>// ...省略很多的图片
// 这里开始是js代码,没有写script,只是简单的模拟
function $(t){
    return document.getElementsByTagName(t);
}

// 获取id
function lazyLoad(el) {
    // 遍历需要加载的图片元素
    for (var i = 0, len = el.length; i < len; i++) {
        // 根据class属性判断是否已经加载过
        if (el[i].className != "load") {
            // 这里就是获取data-url的值,也就是真实图片路径,替代loading图片
            el[i].src = el[i].getAttribute("data-url");
            // 替代后加一个class属性已经加载过的标记
            el[i].className = "load"; 
        }
    }
};

// 滚动时执行
window.onscroll = function() { 
    lazyLoad($("img"));
};
 // 加载后执行
window.onload = function() {
    lazyLoad($("img"));
}; 

这里只是简单的模拟,代码量少,应该可以很容易看懂,懒加载运用比较广泛,可以提高性能,京东首页目前也是这么做的。

这一回,主要聊了代理模式,虚拟代理,图片懒加载,难度适中~~
下一回,聊一下适配器模式,难度也比较小。

客观看完点个赞,推荐推荐呗,嘿嘿~~


注:此系飞狐原创,转载请注明出处


飞狐
2.4k 声望1.4k 粉丝

专注AI量化,技术界最懂金融的CFA金融分析师