脚本沙盒模式的实施实例[英] Javascript Sandbox Pattern example implementation

本文是小编为大家收集整理的关于脚本沙盒模式的实施实例的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

在Stoyan Stefanov的出色书《 JavaScript图案》的第101页上,他解释了沙盒图案. 我非常喜欢他的书,但我真的在这里错过了一些现实生活中的例子,然后更好地理解了他的谈论. 喜欢砂盒模式!/p>

我正在寻找现实生活中的实施,例如复制和粘贴起点,只是一个简单的示例,可以完全理解它.

有吗?

推荐答案

我已经简化了Stoyan的示例,以使其更容易理解发生了什么.我也更彻底地评论了它.

/*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在同一章中提到 yui版本3实现沙盒模式. yui添加方法/docs/api/classes/yui.html#method_add" rel =" nofollow">(api) 注册模块和使用方法 (( API)在沙盒实例中加载指定的. API文档中有指向源JS文件的链接. 几乎所有YUI代码示例使用此模式与YUI库一起使用.很少需要定义一个模块-YUI有许多核心,并且有一个 page 对于社区添加的自定义模块.

其他推荐答案

所以我尝试并提出了这个解决方案:

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()
);

本文地址:https://www.itbaoku.cn/post/627762.html

问题描述

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()
);