简体   繁体   English

如何避免 JavaScript 中的全局变量?

[英]How to avoid global variables in JavaScript?

We all know that global variables are anything but best practice.我们都知道全局变量绝不是最佳实践。 But there are several instances when it is difficult to code without them.但是有几个例子是没有它们就很难编码。 What techniques do you use to avoid the use of global variables?您使用什么技术来避免使用全局变量?

For example, given the following scenario, how would you not use a global variable?例如,给定以下场景,您将如何不使用全局变量?

JavaScript code: JavaScript 代码:

var uploadCount = 0;

window.onload = function() {
    var frm = document.forms[0];

    frm.target = "postMe";
    frm.onsubmit = function() {
        startUpload();
        return false;
    }
}

function startUpload() {
    var fil = document.getElementById("FileUpload" + uploadCount);

    if (!fil || fil.value.length == 0) {
        alert("Finished!");
        document.forms[0].reset();
        return;
    }

    disableAllFileInputs();
    fil.disabled = false;
    alert("Uploading file " + uploadCount);
    document.forms[0].submit();
}

Relevant markup:相关标记:

<iframe src="test.htm" name="postHere" id="postHere"
  onload="uploadCount++; if(uploadCount > 1) startUpload();"></iframe>

<!-- MUST use inline JavaScript here for onload event
     to fire after each form submission. -->

This code comes from a web form with multiple <input type="file"> .此代码来自具有多个<input type="file">的 web 表单。 It uploads the files one at a time to prevent huge requests.它一次上传一个文件以防止大量请求。 It does this by POST ing to the iframe, waiting for the response which fires the iframe onload, and then triggers the next submission.它通过POST到 iframe 来执行此操作,等待触发 iframe onload 的响应,然后触发下一次提交。

You don't have to answer this example specifically, I am just providing it for reference to a situation in which I am unable to think of a way to avoid global variables.您不必专门回答这个例子,我只是提供它以供参考,在这种情况下我无法想出避免全局变量的方法。

The easiest way is to wrap your code in a closure and manually expose only those variables you need globally to the global scope:最简单的方法是将您的代码包装在一个闭包中,并仅手动将您需要全局的那些变量公开到全局范围:

(function() {
    // Your code here

    // Expose to global
    window['varName'] = varName;
})();

To address Crescent Fresh's comment: in order to remove global variables from the scenario entirely, the developer would need to change a number of things assumed in the question.为了解决 Crescent Fresh 的评论:为了从场景中完全删除全局变量,开发人员需要更改问题中假设的一些事情。 It would look a lot more like this:它看起来更像这样:

Javascript: Javascript:

(function() {
    var addEvent = function(element, type, method) {
        if('addEventListener' in element) {
            element.addEventListener(type, method, false);
        } else if('attachEvent' in element) {
            element.attachEvent('on' + type, method);

        // If addEventListener and attachEvent are both unavailable,
        // use inline events. This should never happen.
        } else if('on' + type in element) {
            // If a previous inline event exists, preserve it. This isn't
            // tested, it may eat your baby
            var oldMethod = element['on' + type],
                newMethod = function(e) {
                    oldMethod(e);
                    newMethod(e);
                };
        } else {
            element['on' + type] = method;
        }
    },
        uploadCount = 0,
        startUpload = function() {
            var fil = document.getElementById("FileUpload" + uploadCount);

            if(!fil || fil.value.length == 0) {    
                alert("Finished!");
                document.forms[0].reset();
                return;
            }

            disableAllFileInputs();
            fil.disabled = false;
            alert("Uploading file " + uploadCount);
            document.forms[0].submit();
        };

    addEvent(window, 'load', function() {
        var frm = document.forms[0];

        frm.target = "postMe";
        addEvent(frm, 'submit', function() {
            startUpload();
            return false;
        });
    });

    var iframe = document.getElementById('postHere');
    addEvent(iframe, 'load', function() {
        uploadCount++;
        if(uploadCount > 1) {
            startUpload();
        }
    });

})();

HTML: HTML:

<iframe src="test.htm" name="postHere" id="postHere"></iframe>

You don't need an inline event handler on the <iframe> , it will still fire on each load with this code.不需要<iframe>上的内联事件处理程序,它仍然会在每次加载时触发此代码。

Regarding the load event关于加载事件

Here is a test case demonstrating that you don't need an inline onload event.这是一个测试用例,表明您不需要内联onload事件。 This depends on referencing a file (/emptypage.php) on the same server, otherwise you should be able to just paste this into a page and run it.这取决于引用同一服务器上的文件 (/emptypage.php),否则您应该能够将其粘贴到页面中并运行它。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>untitled</title>
</head>
<body>
    <script type="text/javascript" charset="utf-8">
        (function() {
            var addEvent = function(element, type, method) {
                if('addEventListener' in element) {
                    element.addEventListener(type, method, false);
                } else if('attachEvent' in element) {
                    element.attachEvent('on' + type, method);

                    // If addEventListener and attachEvent are both unavailable,
                    // use inline events. This should never happen.
                } else if('on' + type in element) {
                    // If a previous inline event exists, preserve it. This isn't
                    // tested, it may eat your baby
                    var oldMethod = element['on' + type],
                    newMethod = function(e) {
                        oldMethod(e);
                        newMethod(e);
                    };
                } else {
                    element['on' + type] = method;
                }
            };

            // Work around IE 6/7 bug where form submission targets
            // a new window instead of the iframe. SO suggestion here:
            // http://stackoverflow.com/q/875650
            var iframe;
            try {
                iframe = document.createElement('<iframe name="postHere">');
            } catch (e) {
                iframe = document.createElement('iframe');
                iframe.name = 'postHere';
            }

            iframe.name = 'postHere';
            iframe.id = 'postHere';
            iframe.src = '/emptypage.php';
            addEvent(iframe, 'load', function() {
                alert('iframe load');
            });

            document.body.appendChild(iframe);

            var form = document.createElement('form');
            form.target = 'postHere';
            form.action = '/emptypage.php';
            var submit = document.createElement('input');
            submit.type = 'submit';
            submit.value = 'Submit';

            form.appendChild(submit);

            document.body.appendChild(form);
        })();
    </script>
</body>
</html>

The alert fires every time I click the submit button in Safari, Firefox, IE 6, 7 and 8.每次我在 Safari、Firefox、IE 6、7 和 8 中单击提交按钮时都会触发警报。

I suggest the module pattern .我建议使用模块模式

YAHOO.myProject.myModule = function () {

    //"private" variables:
    var myPrivateVar = "I can be accessed only from within YAHOO.myProject.myModule.";

    //"private" method:
    var myPrivateMethod = function () {
        YAHOO.log("I can be accessed only from within YAHOO.myProject.myModule");
    }

    return  {
        myPublicProperty: "I'm accessible as YAHOO.myProject.myModule.myPublicProperty."
        myPublicMethod: function () {
            YAHOO.log("I'm accessible as YAHOO.myProject.myModule.myPublicMethod.");

            //Within myProject, I can access "private" vars and methods:
            YAHOO.log(myPrivateVar);
            YAHOO.log(myPrivateMethod());

            //The native scope of myPublicMethod is myProject; we can
            //access public members using "this":
            YAHOO.log(this.myPublicProperty);
        }
    };

}(); // the parens here cause the anonymous function to execute and return

First off, it is impossible to avoid global JavaScript, something will always be dangling the global scope.首先,要避免全局 JavaScript 是不可能的,总有东西在全局范围内晃来晃去。 Even if you create a namespace, which is still a good idea, that namespace will be global.即使您创建了一个名称空间(这仍然是一个好主意),该名称空间也将是全局的。

There are many approaches, however, to not abuse the global scope.然而,有许多方法可以避免滥用全局范围。 Two of the simplest are to either use closure, or since you only have one variable you need to keep track of, just set it as a property of the function itself (which can then be treated as a static variable).最简单的两个是使用闭包,或者由于您只有一个需要跟踪的变量,只需将其设置为函数本身的属性(然后可以将其视为static变量)。

Closure关闭

var startUpload = (function() {
  var uploadCount = 1;  // <----
  return function() {
    var fil = document.getElementById("FileUpload" + uploadCount++);  // <----

    if(!fil || fil.value.length == 0) {    
      alert("Finished!");
      document.forms[0].reset();
      uploadCount = 1; // <----
      return;
    }

    disableAllFileInputs();
    fil.disabled = false;
    alert("Uploading file " + uploadCount);
    document.forms[0].submit();
  };
})();

* Note that incrementing of uploadCount is happening internally here * 请注意, uploadCount的递增发生在内部

Function Property函数属性

var startUpload = function() {
  startUpload.uploadCount = startUpload.count || 1; // <----
  var fil = document.getElementById("FileUpload" + startUpload.count++);

  if(!fil || fil.value.length == 0) {    
    alert("Finished!");
    document.forms[0].reset();
    startUpload.count = 1; // <----
    return;
  }

  disableAllFileInputs();
  fil.disabled = false;
  alert("Uploading file " + startUpload.count);
  document.forms[0].submit();
};

I'm not sure why uploadCount++; if(uploadCount > 1) ...我不知道为什么要uploadCount++; if(uploadCount > 1) ... uploadCount++; if(uploadCount > 1) ... is necessary, as it looks like the condition will always be true. uploadCount++; if(uploadCount > 1) ...是必要的,因为看起来条件总是为真。 But if you do need global access to the variable, then the function property method I described above will allow you to do so without the variable actually being global.但是,如果您确实需要对变量进行全局访问,那么我上面描述的函数属性方法将允许您这样做,而变量实际上是全局的。

<iframe src="test.htm" name="postHere" id="postHere"
  onload="startUpload.count++; if (startUpload.count > 1) startUpload();"></iframe>

However, if that's the case, then you should probably use an object literal or instantiated object and go about this in the normal OO way (where you can use the module pattern if it strikes your fancy).但是,如果是这种情况,那么您可能应该使用对象文字或实例化对象并以正常的 OO 方式进行处理(如果您喜欢,您可以使用模块模式)。

Sometimes it makes sense to have global variables in JavaScript.有时在 JavaScript 中使用全局变量是有意义的。 But don't leave them hanging directly off window like that.但不要让它们像那样直接挂在窗外。

Instead, create a single "namespace" object to contain your globals.相反,创建一个单一的“命名空间”对象来包含你的全局变量。 For bonus points, put everything in there, including your methods.对于奖励积分,把所有东西都放在那里,包括你的方法。

window.onload = function() {
  var frm = document.forms[0];
  frm.target = "postMe";
  frm.onsubmit = function() {
    frm.onsubmit = null;
    var uploader = new LazyFileUploader();
    uploader.startUpload();
    return false;
  }
}

function LazyFileUploader() {
    var uploadCount = 0;
    var total = 10;
    var prefix = "FileUpload";  
    var upload = function() {
        var fil = document.getElementById(prefix + uploadCount);

        if(!fil || fil.value.length == 0) {    
            alert("Finished!");
            document.forms[0].reset();
            return;
         }

        disableAllFileInputs();
        fil.disabled = false;
        alert("Uploading file " + uploadCount);
        document.forms[0].submit();
        uploadCount++;

        if (uploadCount < total) {
            setTimeout(function() {
                upload();
            }, 100); 
        }
    }

    this.startUpload = function() {
        setTimeout(function() {
            upload();
        }, 100);  
    }       
}

Some things are going to be in the global namespace -- namely, whatever function you're calling from your inline JavaScript code.有些东西将在全局命名空间中——即,您从内联 JavaScript 代码中调用的任何函数。

In general, the solution is to wrap everything in a closure:一般来说,解决方案是将所有内容包装在一个闭包中:

(function() {
    var uploadCount = 0;
    function startupload() {  ...  }
    document.getElementById('postHere').onload = function() {
        uploadCount ++;
        if (uploadCount > 1) startUpload();
    };
})();

and avoid the inline handler.并避免使用内联处理程序。

Other way to do this is to create an object and then add methods to it.其他方法是创建一个对象,然后向它添加方法。

var object = {
  a = 21,
  b = 51
};

object.displayA = function() {
 console.log(object.a);
};

object.displayB = function() {
 console.log(object.b);
};

In this way, only object 'obj' is exposed and methods attached to it.通过这种方式,只有对象“obj”被暴露出来并附加了方法。 It is equivalent to adding it in namespace.相当于将其添加到命名空间中。

Using closures might be OK for small to medium projects.对于中小型项目,使用闭包可能没问题。 However, for big projects, you might want to split your code into modules and save them in different files.但是,对于大型项目,您可能希望将代码拆分为模块并将它们保存在不同的文件中。

Therefore I wrote jQuery Secret plugin to solve the problem.因此我写了jQuery Secret 插件来解决这个问题。

In your case with this plugin the code would look something like the following.在您使用此插件的情况下,代码将如下所示。

JavaScript: JavaScript:

// Initialize uploadCount.
$.secret( 'in', 'uploadCount', 0 ).

// Store function disableAllFileInputs.
secret( 'in', 'disableAllFileInputs', function(){
  // Code for 'disable all file inputs' goes here.

// Store function startUpload
}).secret( 'in', 'startUpload', function(){
    // 'this' points to the private object in $.secret
    // where stores all the variables and functions
    // ex. uploadCount, disableAllFileInputs, startUpload.

    var fil = document.getElementById( 'FileUpload' + uploadCount);

    if(!fil || fil.value.length == 0) {
        alert( 'Finished!' );
        document.forms[0].reset();
        return;
    }

    // Use the stored disableAllFileInputs function
    // or you can use $.secret( 'call', 'disableAllFileInputs' );
    // it's the same thing.
    this.disableAllFileInputs();
    fil.disabled = false;

    // this.uploadCount is equal to $.secret( 'out', 'uploadCount' );
    alert( 'Uploading file ' + this.uploadCount );
    document.forms[0].submit();

// Store function iframeOnload
}).secret( 'in', 'iframeOnload', function(){
    this.uploadCount++;
    if( this.uploadCount > 1 ) this.startUpload();
});

window.onload = function() {
    var frm = document.forms[0];

    frm.target = "postMe";
    frm.onsubmit = function() {
        // Call out startUpload function onsubmit
        $.secret( 'call', 'startUpload' );
        return false;
    }
}

Relevant markup:相关标记:

<iframe src="test.htm" name="postHere" id="postHere" onload="$.secret( 'call', 'iframeOnload' );"></iframe>

Open your Firebug , you will find no globals at all, not even the funciton :)打开你的Firebug ,你会发现根本没有全局变量,甚至没有函数 :)

For full documentation, please see here .有关完整文档,请参见此处

For a demo page, please see this .有关演示页面,请参阅

Source code on GitHub . GitHub 上的源代码

I use it this way:我这样使用它:

{
    var globalA = 100;
    var globalB = 200;
    var globalFunc = function() { ... }

    let localA = 10;
    let localB = 20;
    let localFunc = function() { ... }

    localFunc();
}

For all global scopes use 'var', and for local scopes use 'let'.对于所有全局范围使用“var”,对于本地范围使用“let”。

Use closures.使用闭包。 Something like this gives you a scope other than global.像这样的东西给你一个全局以外的范围。

(function() {
    // Your code here
    var var1;
    function f1() {
        if(var1){...}
    }

    window.var_name = something; //<- if you have to have global var
    window.glob_func = function(){...} //<- ...or global function
})();

For "securing" induvidual global variables:对于“保护”单个全局变量:

 function gInitUploadCount() { var uploadCount = 0; gGetUploadCount = function () { return uploadCount; } gAddUploadCount= function () { uploadCount +=1; } } gInitUploadCount(); gAddUploadCount(); console.log("Upload counter = "+gGetUploadCount());

I'm a novice to JS, currently using this in one project.我是 JS 的新手,目前在一个项目中使用它。 (i apreciate any comment and criticism) (我感谢任何评论和批评)

What happens is that within the function makeCounter:在函数 makeCounter 中会发生什么:

function makeCounter() {
  var i = 0;
  return function() {
    console.log( ++i );
  };
}

You are returning a function, then to use it is the following:您正在返回一个函数,然后使用它如下:

const counter = makeCounter(); // execute function and return other function
counter(); // This executes the function that you returned

If for example you did not return a function, it would work as expected:例如,如果您没有返回函数,它将按预期工作:

function makeCounter() {
    var i = 0;
    console.log( ++i );
}

makeCounter(); // this execute logs

One fun (YDOFMV 1 ) way to avoid scope clutter for not just JavaScript but also HTML and even CSS(.) is with HTML templates. One fun (YDOFMV 1 ) way to avoid scope clutter for not just JavaScript but also HTML and even CSS(.) is with HTML templates. You do have to whip up a little architectural code (which of course doesn't have to be in global scope): Consider this HTML:您确实必须编写一些架构代码(当然不必在全局范围内):考虑这个 HTML:

<html lang="en">
    <head>
        <title>Templates Are Fun!</title>
        <script> // stuff!
        </script>
    </head>
    <body>
    <template>
        <style> these style directives are local!</style>
        <div> just about any html stuff! </div>
        <script>
            doStuff(); // this code ignored unless you eval it!
        </script>
    </template>
    </body>
</html>

All the stuff in the template has no effect on your HTML page, so what good is it? template中的所有内容对您的 HTML 页面没有影响,那有什么好处呢? First, the style element only affects HTML elements inside the template .首先, style元素只影响template内的 HTML 元素。 Second, the script element is not actually evaluated, which means you can do that yourself and put the code inside a scope of your own choosing, with whatever environmental features you care to give it (all without messing about with "components" and whatnot).其次, script元素实际上并没有被评估,这意味着您可以自己执行此操作并将代码放入您自己选择的 scope 中,并带有您想要提供的任何环境功能(所有这些都不会弄乱“组件”之类的东西) .

On to the minor architecture you have to (get to:) do yourself:在次要架构上,您必须(开始:)自己动手:

For Each Template对于每个模板

Obviously, if you were doing a little single-page app, you could put each page in a separate template, then you swap in the rendered template as needed.显然,如果你在做一个小的单页应用程序,你可以将每个页面放在一个单独的模板中,然后根据需要交换渲染的模板。 Left as an exercise for the reader, but works great.留给读者作为练习,但效果很好。

Also, this concept works great for recursive templates.此外,这个概念非常适合递归模板。 Ie, the whole page is one big template, but it contains smaller templates (navigation bar, footer, etc.).即,整个页面是一个大模板,但它包含较小的模板(导航栏、页脚等)。 Again, left as an exercise, but can't be that hard if I did it.再次,作为练习离开,但如果我这样做了,就不会那么难了。

Whatever your scheme, you're going to need to get hold of that template node, set aside the script sub-node (so you can control its execution), and then replace the template node with the actual contents of the template.无论您的方案是什么,您都需要获取该模板节点,留出script子节点(以便您可以控制其执行),然后将模板节点替换为模板的实际内容。 Your code may look at least vaguely like:您的代码可能看起来至少有点像:

const template     = document.querySelector('template');
const templateRoot = template.content;
const scriptNode   = templateRoot.querySelector('script');
scriptNode.remove(); // take it out of the template
template.replaceWith(templateRoot); // replace template with its contents

After that code runs, the template contents now exist in your document and will no longer be ignored by the DOM parser.在该代码运行后, template内容现在存在于您的文档中,并且不再被 DOM 解析器忽略。 The script element still hasn't been executed but you have a reference to it in scriptNode . script元素仍未执行,但您在scriptNode中有对它的引用。

Control That Script控制该脚本

You could eval the script, of course, but we're talking about limiting scope to avoid problems right?当然,您可以eval脚本,但我们正在谈论限制 scope 以避免出现问题,对吧? Use the Function constructor instead for greater control:使用Function构造函数来获得更好的控制:

const code = '"use strict";' + scriptNode.innerHTML;
const templateFunc = new Function(code);
// now run templateFunc when you want

Note the injection of "use strict" , because the code being evaluated does not inherit that setting from the calling code.请注意"use strict"的注入,因为正在评估的代码不会从调用代码继承该设置。

The code from the template script tag doesn't have access to much of anything other than the global scope, so you don't have to worry much about it colliding with any of your other code.除了全局 scope 之外,模板script标签中的代码无法访问任何其他内容,因此您不必担心它会与您的任何其他代码发生冲突。 Of course, that leads immediately to the problem that you may need that code have some interaction with the rest of your code.当然,这会立即导致您可能需要该代码与您的代码的 rest 进行一些交互的问题。

Letting The Outside Call In让外线呼入

The "module" pattern works fine here. “模块”模式在这里工作得很好。 Since the template script will be wrapped in an anonymous function by the Function constructor, it can just return some interface that suits you:由于模板script将由Function构造函数包装在匿名 function 中,因此它可以只返回一些适合您的接口:

// from inside template <script>
function init() { outside calls me to let me initialize };
function render() { outside calls me to tell me to render };
return {init:init, render:render};

Your world outside the template(s) then keeps that return value around to call into the template script code:然后,您在模板之外的世界保留该返回值以调用模板script代码:

const code = '"use strict";' + scriptNode.innerHTML;
const templateFunc = new Function(code);
const templateInterface = templateFunc();
// let's tell the template script to initialize
templateInterface.init();

Letting the Inside Call Out让内心呼唤

Besides the need to tell the template script what to do, the template script probably needs some limited access to the outside world.除了需要告诉模板script要做什么之外,模板script可能还需要对外部世界进行一些有限的访问。 Again, we want to exercise total control over that access.同样,我们希望完全控制该访问。 Once again, some flavor of "module" pattern works fine.再一次,一些“模块”模式的味道很好。

Suppose that we have an interface called "model" that contains data some template script s may need in order to render.假设我们有一个名为“模型”的接口,其中包含一些模板script可能需要渲染的数据。 Let's roll our own require function, which we inject into the script code by making require an argument to the anonymous function that the Function constructor creates:让我们推出自己的require function,我们通过将require参数添加到Function构造函数创建的匿名 function 的参数来注入script代码:

// revised to give <script> code access to a 'require' function

// model defined elsewhere in this scope
function require(name){
    switch(name){
        case 'model' : return model;
    // etc.
    }
}
const code = '"use strict";' + scriptNode.innerHTML;
// anonymous function will have arg named "require"
const templateFunc = new Function("require", code);
const templateInterface = templateFunc(require);
// let's tell the template script to initialize
templateInterface.init();

Now the code inside the template script has access to a variable (first argument of the anonymous function that encloses it) named require that it can use in the standard ways:现在,模板script中的代码可以访问一个名为require的变量(包含它的匿名 function 的第一个参数),它可以以标准方式使用:

<script>
    const model = require('model');
    // remaining code has access to model forever more
//...
<script>

Enriching the Environment丰富环境

Of course, you can enrich the environment of the script code far beyond just giving it a require function.当然,您可以丰富script代码的环境,而不仅仅是给它一个require function。 This is why there are a billiondy frameworks for JavaScript.这就是为什么 JavaScript 有十亿个框架的原因。 One I like is generating on the fly an object for each template that gives access to DOM elements it is interested in inside the template.我喜欢的一种方法是为每个模板动态生成一个 object,它可以访问模板中感兴趣的 DOM 元素。 This addresses the annoying problem that you often want to locate DOM elements by id , but then you have that nagging feeling that you're supposed to make all id s unique across the entire document, so id effectively becomes a global variable that you can't modularize.这解决了您经常希望通过id定位 DOM 元素的烦人问题,但是您有一种烦人的感觉,即您应该使整个文档中的所有id都是唯一的,因此id有效地成为了一个全局变量,您可以t 模块化。

Suppose that inside the template, you identify elements your script code cares about with a data-id tag:假设在模板中,您使用data-id标记识别script代码关心的元素:

<template>
    <dialog id="PickOrCreateProject">
        <center>
        Project name: <input type="text" data-id="textProject" />
        <input type="button" value="Create" data-id="createButton">
        <br/>
        <div data-id="div">
            <select data-id="select"></select>
            <input type="button" value="Select" data-id="selectButton">
        </div>
        </center>
    </dialog>
    <script> etc.</script>
</template>

And suppose that we want to give our script code easy access to an object (call it viewNodes ) that contains references to each node inside the template marked with a data-id attribute, such that the script can do this:并假设我们想让我们的脚本代码轻松访问 object(称为viewNodes ),其中包含对模板内每个节点的引用,并标记有data-id属性,这样脚本就可以这样做:

const {textProject,createButton,selectButton} = viewNodes;

You can whip that up as easy as:您可以像这样简单地鞭打它:

let viewNodes = {};
for(const element of templateRoot.querySelectorAll("[data-ID]"))
    viewNodes[element.dataset.id] = element;

And revise the Function constructor to supply it to the script code:并修改Function构造函数以将其提供给script代码:

const templateFunc = new Function("require", "viewNodes", code);
const templateInterface = templateFunc(require, viewNodes);

Doesn't matter if two different templates use conflicting data-id attributes, since no template ever looks outside itself for the identifiers it wants.两个不同的模板是否使用冲突data-id属性无关紧要,因为没有模板会在其外部寻找它想要的标识符。

Conclusion结论

In conclusion, templates are fun for modularity, and I must have some work I am procrastinating hard on to waste time spewing this all out:-).总之,模板对于模块化很有趣,而且我必须有一些我正在努力拖延的工作来浪费时间把这一切都吐出来:-)。


1 Your Definition Of Fun May Vary 1您对乐趣的定义可能会有所不同

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM