javascript中的#ifndef

时间:2011-09-11 03:27:22

标签: javascript preprocessor

我正在寻找一种解决方案,只在Javascript中使用与编译语言中的#ifndef类似的东西定义一次函数。我发现了一些应该模仿这个功能的库,但它们没有用。

我正在使用MVC 3 Razor并定义了一些html助手,它们确实将用户控件放在页面上。

每个控件都有一组javascript函数,用于定义该控件的特定功能,因此这里存在一个问题:当在单个页面上多次调用帮助程序时,函数会多次定义。

我希望找到一种方法来保持帮助程序中定义的少量javascript,而不必将这些小帮助程序中的每一个javascript分成一个单独的文件。

样品:

@helper CmsImage(int id)
{
  var Html = ((System.Web.Mvc.WebViewPage)WebPageContext.Current.Page).Html;

  <text>
    <input type="button" class="editor_function" style="display: none;" onclick="editImage(@id); return false;" />
    <script>
        function editImage(id) {
            $('#alt_text' + id).attr('value', $('#' + id).attr('alt'));
            $('#image_url' + id).attr('value', $('#' + id).attr('src'));
        }

        function saveImage(button, id) {
            $(button).parent().parent().removeClass('color-yellow').addClass('color-red');
            $(button).parent().siblings('div.widget-content').html('<img alt="' + $('#alt_text' + id).val() + '" src="' + $('#image_url' + id).val() + '" id="' + id + '" />');
        }
        #endif 
    </script>
    Image Url:
    <input type="text" id="image_url@{id.ToString();}" /><br />
    Alt Text:
    <input type="text" id="alt_text@{id.ToString();}" /><br />
    <input type="button" value="save" onclick="saveImage(this, @{id.ToString();});" />
    @Html.Raw(GetCurrentContent(id))
  </text>
}

以上在浏览器中不起作用,如果给我错误:'48:无法识别的令牌ILLEGAL'

7 个答案:

答案 0 :(得分:12)

正如我所知,Javascript没有像C / C ++这样的预处理程序指令,但您可以使用在运行时评估的常规if语句,如下所示:

if (typeof myFunc === "undefined") {
    var myFunc = function(a,b) {
        // body of your function here
    }
}

或整个函数库:

if (!window.controlUtilsDefined) {
    window.controlUtilsDefined = true;

    // put control library functions here

    function aaa() {
        // body here
    }

    function bbb() {
        // body here
    }

}

或者如果您想根据其他变量进行检查:

var myFunc;
if (debugMode) {
    myFunc = function(a,b) {
        // body of your function here
    }
} else {
    myFunc = function(a,b) {
        // body of your alternate function here
    }
}

如果你担心的是你在每个控件使用的库中拥有完全相同的函数名的多个副本,那么这在技术上不是Javascript中的问题。最后定义的一个将是可操作的,但如果它们都是相同的,那在技术上不是问题。内存中只有一个定义,因为后面的定义将取代之前的定义。

如果您控制控件的来源,那么最好将常用实用程序单独分解为自己的JS文件,并让主页只包含该实用程序脚本文件一次。

或者(对于主机页面稍微多做一些工作但没有额外的责任),每个控件都可以从外部JS文件中动态加载它们的权限并检查已知的全局变量以查看是否有其他控件已经加载了公共外部JS。

答案 1 :(得分:8)

如果您有一些构建脚本,我建议使用GPP预处理器(http://en.nothingisreal.com/wiki/GPP或赢取版本http://makc.googlecode.com/svn/trunk/gpp.2.24-windows/

所以你需要做以下的步骤:

  1. gpp -o _script.js script.js (其中_script.js - 带有预处理器的源文件 命令)
  2. (可选)缩小script.js(使用谷歌闭包编译器等)
  3. 将script.js部署到您的网络文件夹。
  4. 在这种情况下,您将获得最优化的js代码。您不需要运行时检查

    #define debugMode
    #ifdef debugMode
        var myFunc = function(a,b) {
            // body of your function here
        }
    #else
        var myFunc = function(a,b) {
            // body of your alternate function here
        }
    #endif
    

答案 2 :(得分:5)

我看到,当node.js不在时,jfriend提供的答案有点旧。 PLS。检查最新的preprocessor.js(可通过npm install获得)。

您可以使用下面的静态条件(来自文档)

 // #ifdef FULL
console.log("Including extension");
// #include "path/to/extension.js"
// #else
console.log("Not including extension");
// #endif

用法是:


    Usage: preprocess sourceFile [baseDirectory] [-myKey[=myValue], ...] [> outFile]

    preprocess Source.js . -FULL=true > Source.full.js

答案 3 :(得分:2)

这是一个老问题,但答案现在有些过时了。如果您想要更好地内联或消除死代码,可以使用谷歌的closure compiler/** @const */帮助

以下是使用高级优化的@const助手的完全随机(无用的演示除外)示例:

/** @const */
var G=true

if(G){var d=document}
function dummy(){if(!G){var d=document}return d.getElementsByTagName("body")[0]}
function hello(name) {
alert(dummy() + name + dummy());
}
hello('New user');

编译为:alert((void 0).getElementsByTagName("body")[0]+"New user"+(void 0).getElementsByTagName("body")[0]);

或没有@const:var a=!0;function b(){if(!a)var c=document;return c.getElementsByTagName("body")[0]}alert(b()+"New user"+b());

这样做的好处是代码在开发过程中仍然可以工作,而无需在每次运行之前对其进行预处理。 (具有更好的优化的额外好处)

答案 4 :(得分:2)

旧主题,但对于对所需解决方案感兴趣的任何人,我写了 jspreproc 来部署一些riot模块,所有这些都在JavaScript中用于节点0.10.0及更高版本。

jspreproc是开源的,删除空行,支持保存不同类型注释的过滤器,以及C风格的条件注释:

  • #if, #elif, #else, #endif带有表达式和defined()支持
  • #define包含表达式和基本的宏替换
  • #ifdef, #ifndef
  • #include, #include_once

安装和使用示例:

$ npm -g i jspreproc
$ jspp -D RELEASE --empty-lines 0 lib/file1.js lib/file2.js > dist/app.js

在github上的jspreproc repository阅读更多内容。

答案 5 :(得分:1)

在现代,它看起来像RequireJS或同等AMD模块的工作。 所有其他答案都谈到预编译和缩小 - 这些都是好的,并且应该另外考虑。

答案 6 :(得分:0)

不可能在JavaScript中使用预处理器或#define函数... JavaScript是松散耦合和解释的语言.....但是您可以在Typescript中使用它,因为它是强耦合并且使用编译器...