YUI3的沙箱机制

2010-4-10

YUI2

在YUI2.x里,每一个模块功能的引入都会直接添加在全局的YAHOO里,例如dom.js里:

var Y = YAHOO.util;
Y.Dom = {...}

这样在整个页面范围内,YAHOO.util里就多了一个功能Dom。

YUI3-add()

在YUI3里,每一个模块引入时并没有把功能直接添加到全局的YUI里,看看YUI3里的dom.js:

YUI.add('dom-base', function(Y) {
    //在这里添加dom方法
    Y.DOM = {
        ...
    }
...
}, '3.0.0' );

再看看yui.js里add的源码:

add: function(name, fn, version, details) {

    YUI.Env.mods[name] = {
        name: name,
        fn: fn,
        version: version,
        details: details || {}
    };

    return this; // chain support
}

所以YUI3里引入每个模块时只是把这个模块的内容储存在YUI.Evn.mods里。

YUI3-use()

需要使用某个模块时,在创建YUI实例以后,用use取出来执行模块里的程序,为这个YUI实例添加相应的方法:

YUI().use('dom-base', function(Y) {
    //这里可以用到模块dom-base里对YUI添加的方法Y.DOM
    alert(Y.DOM) //[object object]
})

而在同一个页面里,YUI实例里如果没有指明use(‘dom-base’),就没有Y.DOM这个方法

YUI().use('', function(Y) {
    alert(Y.DOM) //undefined
})

沙箱

这里YUI().use(”,function(Y){…})就是一个安全沙箱,可以确保这里面的Y是纯天然无污染的,Y实例里有什么功能完全取决于use里传进的模块名称,function(Y){}里面的程序跟外界是隔离的,在里面创建的变量(除了全局变量)以及对YUI的添加修改都不会影响到同个页面上其他人写的程序。

但是这个纯天然无污染是有点代价的,就是每次都要新建一个YUI实例,消耗内存,但如果不怕Y被污染,可以不每次都创建实例:

var Y = YUI();
Y.use('dom-base', function(Y) {
    //可以同时使用dom-base和oop模块里添加的方法
});
Y.use('oop', function(Y) {
    //可以同时使用dom-base和oop模块里添加的方法
});

add()和use()配合一些参数(例如require)和YUI Loader就成了YUI3模块化编程的基础。

最简化的YUI沙箱

去除了YUI Loader以及require等参数,参考自这里

if (typeof YUI === 'undefined' || !YUI) {
    YUI = function() {
        var Y = this;

        if (!(Y instanceof YUI)) { 
            return new YUI();
        } else {
            Y._init();
            return Y;
        }
    };
}
//保存mod列表的静态属性
YUI.Env = {
    mods: {}
};
(function() {
    var SLICE = Array.prototype.slice;
    YUI.prototype = {
        _init: function() {
            var Y  = this,
                G_Env = YUI.Env,
                Env   = Y.Env;
            if(!Env) {
                Y.Env = {
                    mods: {},
                    _used: {},
                    _attached: {}
                };
                Env = Y.Env;
            }
            Y.constructor = YUI;

        },
        add: function(name, fn, details) {
            YUI.Env.mods[name] = {
                name: name,
                fn: fn,
                details: details || {}
            };
            return this; // chain support
        },
        _attach: function(r) {

            var mods = YUI.Env.mods,
                Y = this,
                attached = Y.Env._attached,
                i, l = r.length, name, m, fn, d;

            for (i = 0; i < l; i = i+1) {
                name = r[i];
                m    = mods[name];
                if (!attached[name] && m) {
                    attached[name] = true;                    
                    fn  = m.fn;
                    d   = m.details;
                    if (fn) {
                        fn(Y);
                    }
                }
            }

        },
        use: function() {

            var Y = this,
                a = SLICE.call(arguments, 0),
                mods = YUI.Env.mods,
                used = Y.Env._used,                
                callback = a[a.length-1],
                i, l,
                r = [],
                process = function(name) {
                    // 添加模块至附加的模块列表
                    r.push(name);
                    // 一个模块仅附加一次
                    if (used[name]) {
                        return;
                    }
                    var m = mods[name];
                    if (m) {
                        used[name] = true;
                    }
                },
                onComplete;

            if (typeof callback === 'function') {
                a.pop();
            } else {
                callback = null;
            }
			l = a.length;
			for (i = 0; i < l; i = i + 1) {
                process(a[i]);
            }
            Y._attach(r);
			if (callback) {
				callback(Y);
			}
            return Y; // chain support
        }
    };
})();
YUI().add('test',function(){document.write("<p>test module add() excute</p>")});
YUI().use('test',function(){document.write("<p>test module has executed completely.</p>")});
评论

2010年4月13日 17:47

推特中文圈是不是被墙奸了。无法使用了?

2016年9月1日 23:34

谢谢你了