问题描述
在Stoyan Stefanov的出色书《 JavaScript图案》的第101页上,他解释了沙盒图案.
我非常喜欢他的书,但我真的在这里错过了一些现实生活中的例子,然后更好地理解了他的谈论.
喜欢砂盒模式!/p>
我正在寻找现实生活中的实施,例如复制和粘贴起点,只是一个简单的示例,可以完全理解它. 有吗? 我已经简化了Stoyan的示例,以使其更容易理解发生了什么.我也更彻底地评论了它. Stoyan Stefanov在同一章中提到 yui版本3实现沙盒模式. yui添加方法推荐答案
/*First define the modules of the sandbox. These will be defined
as properties on the constructor function because this is a
convenient place to keep them.*/
Sandbox.modules = {};
Sandbox.modules.returnNumbers = function(MYAPP) {
MYAPP.return100 = function() {return 100;};
};
Sandbox.modules.returnLetters = function(MYAPP) {
MYAPP.returnABC = function() {return "ABC";};
};
function Sandbox() {
/* Because Sandbox is a constructor, an new object is automatically
created. Because we're in the constructor, we refer to this new object
as 'this'.
A constructor would typically be used as part of an assignment, e.g.
myObject = new Sandbox().
However, it's also legitimate javascript to use a constructor without
the assignment by just writing new Sandbox() with no assignment. The
constructor does return an object, it's just that it doesn't get
assigned to anything so is discarded.
We're going to add functionality (methods) to the 'this' object, but
rather than returning it, we will pass it to the callback function, so
the methods can be used immediately.
*/
var args = Array.prototype.slice.call(arguments); //Put the arguments
//of the call to the Sandbox constructor in an array called args.
var callback = args.pop(); //The last argument is the callback
var requiredmodules = args; //The remaining arguments are the require
// modules
//For each of the modules in 'requiredmodules', add the module's
//methods to 'this'
for (i=0; i< requiredmodules.length; i++) {
Sandbox.modules[requiredmodules[i]](this);
}
//'this' now has methods returnNumbers and returnLetters
//Call the callback. In the example below, 'this' will be called
//MYAPP, which within the callback will have all the methods from
//the required modules.
callback(this);
}
//Finally here is an example of usage
new Sandbox('returnNumbers', 'returnLetters', function (MYAPP) {
console.log(MYAPP.return100());
console.log(MYAPP.returnABC());
});
其他推荐答案
其他推荐答案
所以我尝试并提出了这个解决方案:
function Sandbox() { // turning arguments into an array var args = Array.prototype.slice.call(arguments), // the last argument is the callback callback = args.pop(), // modules can be passed as an array or as individual parameters modules = (args[0] && "string" === typeof args[0]) ? args : args[0], i; // make sure the function is called // as a constructor if (!(this instanceof Sandbox)) { return new Sandbox(modules, callback); } // add properties to 'this' as needed: this.a = 1; this.b = 2; // now add modules to the core 'this' object // no modules or "*" both mean "use all modules" if (!modules || '*' === modules) { modules = []; for (i in Sandbox.modules) { if (Sandbox.modules.hasOwnProperty(i)) { modules.push(i); } } } // initialize the required modules for (i = 0; i < modules.length; i += 1) { Sandbox.modules[modules[i]](this); } // call the callback callback(this); // any prototype properties as needed Sandbox.prototype = { name: "Sandbox", version: "1.0", getName: function() { return this.name; } } }; Sandbox.modules = {}; Sandbox.modules.color = function (box) { // private var initialColor = $('#main').css('color'); // set a red color box.setMainRed = function() { $('#main').css('color','red'); return false; }, // get the current color box.getInitialColor = function () { return initialColor; }; } // another module Sandbox.modules.style = function (box) { // set a red color box.setStyle = function() { $('#main').css('font-style','italic'); return false; }; } // page ready $.ready( Sandbox(['color', 'style'], function (box) { console.log(box); box.setMainRed(); box.setStyle(); console.log('try access initialColor: ', box.initialColor); console.log('get initial color: ', box.getInitialColor()); }) );
但我真的不确定天气这是我应该做的. 特别是添加"模块"有些混乱.同样在书中,他将命名空间模式用于此任务,但不在这里.为什么?你也不能在这里做吗? 但是我没有结合这两种模式.
名称空间模式示例受本书的启发:
var APP = APP || {}; // namespace function APP.namespace = function (nsString) { var parts = nsString.split('.'), parent = APP, i; // strip redundant leading global if ("APP" === parts[0]) { parts = parts.slice(1); } for (i = 0; i < parts.length; i += 1) { // create a property if it doesn't exist if ("undefined" === typeof parent[parts[i]]) { parent[parts[i]] = {}; } parent = parent[parts[i]]; } return parent; } // constructors APP.namespace('modules.Color'); // immediate function APP.modules.Color = (function () { var currentColor = $('#main').css('color'), // set a red color setMainRed = function() { $('#main').css('color','red'); return false; }, // get the current color getCurrentColor = function () { return currentColor; }; // revealing module pattern return { setMainRed: setMainRed, getCurrentColor: getCurrentColor }; }()); var doSomething = function () { var color = APP.modules.Color; color.setMainRed(); console.log(color.currentColor); console.log(color.getCurrentColor()); return false; } // page ready $.ready( doSomething() );
问题描述
On Page 101 of Stoyan Stefanov's great book "JavaScript Patterns" he explains the sandbox pattern. I liked his book much but I really missed some real life examples here and then to better understand what he talks about. Like the sandbox pattern!
I'm looking for a real life working implementation, like a copy&paste starting point, just a simple example that will work to fully understand it.
Is there any?
推荐答案
I've simplified Stoyan's example in an attempt to make it easier to understand what's going on. I've also commented it more thoroughly.
/*First define the modules of the sandbox. These will be defined as properties on the constructor function because this is a convenient place to keep them.*/ Sandbox.modules = {}; Sandbox.modules.returnNumbers = function(MYAPP) { MYAPP.return100 = function() {return 100;}; }; Sandbox.modules.returnLetters = function(MYAPP) { MYAPP.returnABC = function() {return "ABC";}; }; function Sandbox() { /* Because Sandbox is a constructor, an new object is automatically created. Because we're in the constructor, we refer to this new object as 'this'. A constructor would typically be used as part of an assignment, e.g. myObject = new Sandbox(). However, it's also legitimate javascript to use a constructor without the assignment by just writing new Sandbox() with no assignment. The constructor does return an object, it's just that it doesn't get assigned to anything so is discarded. We're going to add functionality (methods) to the 'this' object, but rather than returning it, we will pass it to the callback function, so the methods can be used immediately. */ var args = Array.prototype.slice.call(arguments); //Put the arguments //of the call to the Sandbox constructor in an array called args. var callback = args.pop(); //The last argument is the callback var requiredmodules = args; //The remaining arguments are the require // modules //For each of the modules in 'requiredmodules', add the module's //methods to 'this' for (i=0; i< requiredmodules.length; i++) { Sandbox.modules[requiredmodules[i]](this); } //'this' now has methods returnNumbers and returnLetters //Call the callback. In the example below, 'this' will be called //MYAPP, which within the callback will have all the methods from //the required modules. callback(this); } //Finally here is an example of usage new Sandbox('returnNumbers', 'returnLetters', function (MYAPP) { console.log(MYAPP.return100()); console.log(MYAPP.returnABC()); });
其他推荐答案
Stoyan Stefanov mentions in the same chapter that YUI version 3 implements the Sandbox pattern. The YUI add method (API) registers modules and the use method (API) loads the specified ones in the sandbox instance. There are links to the source js file in the API documentation. Virtually all YUI code examples use this pattern to work with the YUI library. Defining a module is rarely needed - YUI has many core ones and there is a page for custom modules added by the community.
其他推荐答案
So I tried and came up with this solution:
function Sandbox() { // turning arguments into an array var args = Array.prototype.slice.call(arguments), // the last argument is the callback callback = args.pop(), // modules can be passed as an array or as individual parameters modules = (args[0] && "string" === typeof args[0]) ? args : args[0], i; // make sure the function is called // as a constructor if (!(this instanceof Sandbox)) { return new Sandbox(modules, callback); } // add properties to 'this' as needed: this.a = 1; this.b = 2; // now add modules to the core 'this' object // no modules or "*" both mean "use all modules" if (!modules || '*' === modules) { modules = []; for (i in Sandbox.modules) { if (Sandbox.modules.hasOwnProperty(i)) { modules.push(i); } } } // initialize the required modules for (i = 0; i < modules.length; i += 1) { Sandbox.modules[modules[i]](this); } // call the callback callback(this); // any prototype properties as needed Sandbox.prototype = { name: "Sandbox", version: "1.0", getName: function() { return this.name; } } }; Sandbox.modules = {}; Sandbox.modules.color = function (box) { // private var initialColor = $('#main').css('color'); // set a red color box.setMainRed = function() { $('#main').css('color','red'); return false; }, // get the current color box.getInitialColor = function () { return initialColor; }; } // another module Sandbox.modules.style = function (box) { // set a red color box.setStyle = function() { $('#main').css('font-style','italic'); return false; }; } // page ready $.ready( Sandbox(['color', 'style'], function (box) { console.log(box); box.setMainRed(); box.setStyle(); console.log('try access initialColor: ', box.initialColor); console.log('get initial color: ', box.getInitialColor()); }) );
But I am really unsure weather this is what I should be doing. Especially adding the "modules" is somewhat confusing. Also earlier in the book he uses the namespace-pattern for this task, but not here. Why? Can't you do it here too? But I failed to combine these two patterns.
Namespace pattern example inspired by the book:
var APP = APP || {}; // namespace function APP.namespace = function (nsString) { var parts = nsString.split('.'), parent = APP, i; // strip redundant leading global if ("APP" === parts[0]) { parts = parts.slice(1); } for (i = 0; i < parts.length; i += 1) { // create a property if it doesn't exist if ("undefined" === typeof parent[parts[i]]) { parent[parts[i]] = {}; } parent = parent[parts[i]]; } return parent; } // constructors APP.namespace('modules.Color'); // immediate function APP.modules.Color = (function () { var currentColor = $('#main').css('color'), // set a red color setMainRed = function() { $('#main').css('color','red'); return false; }, // get the current color getCurrentColor = function () { return currentColor; }; // revealing module pattern return { setMainRed: setMainRed, getCurrentColor: getCurrentColor }; }()); var doSomething = function () { var color = APP.modules.Color; color.setMainRed(); console.log(color.currentColor); console.log(color.getCurrentColor()); return false; } // page ready $.ready( doSomething() );