javascript - Javascript 模块之间共享的全局变量

标签 javascript module revealing-module-pattern

我有一个脚本,我想将其分成多个模块。 例如,将我所有的鼠标事件放在另一个模块中(mouseup、mousedown 等)。

我使用一组全局变量来跟踪屏幕上的所有对象。鼠标模块将需要访问这些变量并更改它们。我意识到我可以向其他模块显示所需的每个变量,但它们无法更改它们。

如何使用 Javascript 最好地实现这一点?我目前使用的是显示模块模式,并且我读到我必须使用 getter 和 setter(例如我在学校记忆起的 C++ 中使用的),但我有相当多的全局变量需要跟踪。我需要相当多的这些方法。这是我应该这样做的方式吗?

或者...这个案例是否向我表明问题描述的是糟糕的设计。

我正在使用 Fabric.js 进行绘图和所有其他操作。

drawscript.js

var DrawScript = function(){

    var DRAW = 0,
        SELECT = 1,
        SCROLL = 2;

    var MOUSEBUTTONS = {
        'S': 83,
        'C': 67,
        'D': 68,
        'DELETE': 46,
        'BACKSPACE': 8
    };

    var canvas;
    var _started       = false;
    var _x, _y;
    var square;
    var edgedetection  = 10; // pixels to snap
    var lines          = {};
    var lines_group;
    var rectangles_group;
    var rectangle_txt  = {};
    var _text_offset_x = 20;
    var _text_offset_y = 20;
    var pressedKeys    = [];

    var _stroke_colour_var    = "red";
    var _stroke_width_var     = 5;
    var _selectionColor       = "rgba(255,255,255,0.4)";
    var _selectionBorderColor = "rgba(0,0,0,0.5)";

    var selectedObjStartSettings = {};
    var resetOpacityOfObject     = false;
    var drawingMode              = true;
    var mouseGlobal              = null;
    var garbage                  = null;

    var window_height        = 0;
    var window_width         = 0;
    var canvasHeight         = 0;
    var canvasWidth          = 0;
    var bg_height            = 0;
    var _canvas_position = {
        'x': {},
        'y': {}
    };
    var _canvas_mouse_pos_x = 0;
    var _canvas_mouse_pos_y = 0;

    var _fullSizeOn      = false;
    var _fullWidth       = 0;
    var _fullHeight      = 0;
    var _fitWidth        = 0;
    var _fitHeight       = 0;
    var _scaleSizeWidth  = 0;
    var _scaleSizeHeight = 0;

    var setCanvasSize = function(){
        // stuff
    },

    checkDrawingMode = function(){
        // stuff
    },

    checkKeyDown = function(e){
        // stuff
    },

    saveDrawing = function(){
        // stuff
    },

    deleteObjectFromCanvas = function (obj){
        // stuff
    },

    setObjectStartPoints = function(){
        // stuff
    },

    drawNewRect = function(top, left, width, height, name){
        // stuff
    },

    updateCoords = function(x, y){
        // stuff
    },

    changeZoom = function(input){
        // stuff
    },

    init = function(){

        garbage = $("#garbage");

        // ===================================
        //  Set drawing mode when changed
        // ===================================
        $("input[name='draw']").change(function(){
            checkDrawingMode();
        });

        // ===================================
        //  Zoom On
        // ===================================
        $("input[name='zoom-on']").change(function(){
            changeZoom(this);
        });

        // ===================================
        //  Check keypress
        // ===================================
        $(document).keydown(function(e){
            checkKeyDown(e);
        });

        $(document).keyup(function(e){
            e.preventDefault();

            var key;

            if(e.metaKey)
            {
                // key = 91;
                return;
            }
            else
                key = e.keyCode;
            pressedKeys[key] = false;

            // console.log(pressedKeys);
        });

        // ===================================
        //  Save drawing
        // ===================================
        $("#save").click(function(){
            saveDrawing();
        });

        $(window).resize(function(){
            setCanvasSize();
        });

        // ===================================
        //  Create canvas and check drawing mode when launched
        // ===================================
        canvas = new fabric.Canvas('demoCanvas');
        setCanvasSize();
        checkDrawingMode();
        canvas.selectionLineWidth = 2;
        canvas.selectionDashArray = [4, 4];
        canvas.cornerColor        = "#900";
        canvas.hoverCursor        = 'pointer';
        canvas.moveCursor         = 'pointer';
        canvas.selection          = false;

        // ===================================
        //  Add groups
        // ===================================
        rectangles_group = new fabric.Group();
        lines_group = new fabric.Group();
        canvas.add(lines_group);

        // ===================================
        //  Get mouse events
        // ===================================
        canvas.on('mouse:down', function(options) { mousedown(options); });
        canvas.on('mouse:move', function(options) { mousemove(options); });
        canvas.on('mouse:up', function(options) { mouseup(options); });
        canvas.on('object:scaling', function(e) { e.target.resizeToScale(rectangle_txt, _text_offset_x, _text_offset_y); });
        canvas.on('object:selected', function() { setObjectStartPoints(); });
        canvas.on('object:moving', function(options) { objectMoving(options); });
    };

    return {
        init: init
    };

}();

为简洁起见,我删除了顶部的函数实现。 此外,我肯定需要使我的变量名在命名约定方面更加统一。这一切都还很早,所以如果这让任何人想打破我的膝盖,我深表歉意!

我不确定如何拆分鼠标事件,以免我的 drawScript.js 文件变成 3k 行。鼠标事件都使用我设置的各种组和坐标变量。此外,我需要在应用程序使用的脚本之间共享 Canvas 。

也许我只是想努力和过度组织,但我认为无论哪种方式寻求帮助都会帮助我在更大的项目中变得更好:)

最佳答案

不要使用揭示模块模式。许多人从 Addy Osmani's book 学习揭示模块模式没有注意Addy's warning .

正如您所发现的,当您向其他模块公开您的闭包变量时,它们将无法更改。这是揭示模块模式的一个根本弱点。你可能做过这样的事情

var mouse = (function(){
  var x = 10, y = 20;
  var drawLineTo = function(x1,y1){
     console.log("Drawing line from " + x + "," + y + " to " + x1 + "," + y1);
  };
  return {
     x: x,
     y: y,
     draw: drawLineTo
  }

})

mouse.x = 50
mouse.draw(15,15) // print "Drawing line from 10,20 to 15,15"

并发现更改 mouse.x 不会更改闭包中 x 的值。虽然您可以像这样定义明确的 getter 和 setter 来解决这个问题

var mouse = (function(){
  var x = 10, y = 20;
  var getX = function() {return x};
  var setX = function(val) {x = val};
  var drawLineTo = function(x1,y1){
     console.log("Drawing line from " + x + "," + y + " to " + x1 + "," + y1);
  };
  return {
     getX : getX,
     setX : setX,
     y: y,
     draw: drawLineTo
  }

})

mouse.setX(50);
mouse.draw(15,15) // print "Drawing line from 10,50 to 15,15"

这只是为使用揭示模块模式付出的愚蠢代价。更简单的是

var mouse = (function(){
  // put your private variables and methods here.
  return {
     x : 10,
     y: 20,
     draw: function(x1,y1){
        console.log("Drawing line from " + this.x + "," + this.y + " to " + x1 + "," + y1)
     }
  }

})

mouse.x = 50;
mouse.draw(15,15) // print "Drawing line from 50,20 to 15,15"

关键是永远不要泄露——只把你想要隐藏的东西放到闭包中。应该公开的东西应该这样创建。

关于javascript - Javascript 模块之间共享的全局变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23521069/

相关文章:

javascript - 将复选框值传递给 Angular 的 ng-click

javascript - 防止功能 Prop 更新时重新渲染

javascript - 在加载页面的所有元素之前加载 Chrome 扩展

angularjs - 如何在客户端使用Node模块?

JavaScript 揭示模块模式变量作用域

javascript - 揭示模块模式 (javascript) - 这无法访问私有(private)方法

javascript - 我如何将键值对添加到javascript中的关联数组

javascript - 如何使 JavaScript 模块在 IE 11 中工作

linux - 如何获取 linux 内核模块的选项列表?

javascript - 揭示模块模式和范围