JavaScript 中的 #ifndef

发布于 2024-12-03 17:19:38 字数 1527 浏览 0 评论 0原文

我正在寻找一种解决方案,只在 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:无法识别的令牌非法”

I am looking for a solution to only define a function once in Javascript using something exactly like #ifndef in compiled languages. I found a couple of libraries that were supposed to mimic this functionality but they didn't work.

I am working with MVC 3 Razor and have defined some html helpers do put what are essentially user controls onto the page.

Each control has a set of javascript functions that define specific functionality for that control, so herein lies the issue: the functions get defined multiple times when the helper is called multiple times on a single page.

I am hoping to find a way to keep the very small amount of javascript defined within the helper and not have to divide all of the javascript for each of these small helpers in a separate file.

Sample:

@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>
}

The above doesn't work in the browser, if gives me the error: '48: Unrecognized token ILLEGAL'

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

剪不断理还乱 2024-12-10 17:19:38

我想您知道,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。

As I presume you know, Javascript doesn't have preprocessor directives like C/C++, but you can use regular if statements that are evaluated at run-time like this:

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

or for a whole library of functions:

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

    // put control library functions here

    function aaa() {
        // body here
    }

    function bbb() {
        // body here
    }

}

or if you want to check based on some other variable:

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

If your concern is just that you have multiple copies of the exact same function names in the library that each control uses, that isn't technically a problem in Javascript. The last defined one will be the operative one, but if they're all the same that isn't technically a problem. Only one definition will exist in memory as the later definitions will replace the earlier ones.

If you control the source of the controls, then it would be better to break the common utilities out separately into their own JS file and have the host page just include that utilities script file once.

Or (with a little more work but no additional responsibilities for the host page), each control could dynamically load their utlities from an external JS file and check a known global variable to see if some other control has already loaded the common external JS.

最笨的告白 2024-12-10 17:19:38

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

因此您需要执行以下步骤:

  1. gpp -o _script.js 脚本.js (其中 _script.js - 带预处理器的源文件
    命令)
  2. (可选)minify script.js(使用谷歌闭包编译器等)
  3. 将 script.js 部署到您的 Web 文件夹。

在这种情况下,您将获得最优化的 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

If you have some build script I suggest to use GPP preprocessor(http://en.nothingisreal.com/wiki/GPP, or win version http://makc.googlecode.com/svn/trunk/gpp.2.24-windows/)

So you need to do the following steps:

  1. gpp -o _script.js script.js (where _script.js - your source file with preprocessor
    commands)
  2. (OPTIONAL) minify script.js (using google closure compiler, etc.)
  3. deploy script.js to your web folder.

In this case you'll get the most optimized js code. And you do not need runtime checks

#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
难忘№最初的完美 2024-12-10 17:19:38

我发现当 node.js 不存在时,jfriend 提供的答案有点旧。请。检查最新的 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

I see that that the answer provided by jfriend is a bit old when node.js is not around. Pls. check the latest preprocessor.js (available through npm install).

You can use the static conditions like below (from documentation)

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

Usage is :


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

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

始终不够爱げ你 2024-12-10 17:19:38

老主题,但对于任何对所需解决方案感兴趣的人,我编写了 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 存储库

Old theme, but for anyone interested in the required solution I wrote jspreproc to deploy some riot modules, all in JavaScript for node 0.10.0 and above.

jspreproc is open source, remove empty lines, supports filters for preserve comments of different types, and conditional comments in C-style:

  • #if, #elif, #else, #endif with expression and defined() support
  • #define with expression and basic macro-replacement
  • #ifdef, #ifndef
  • #include, #include_once

Installation and usage example:

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

Read more at the jspreproc repository on github.

看春风乍起 2024-12-10 17:19:38

这是一个老问题,但答案现在有点过时了。如果您想获得更好的内联或消除死代码,您可以使用 google 的 closure 编译器 以及/** @const */ helper

这是一个完全随机的(除了演示之外无用的)@const helper 使用高级优化的示例:

/** @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]+"新用户"+(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());

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

This is an old question but the answers are now a bit out of date. If you are trying to get better inlining or eliminate dead code you can use google's closure compiler along with the /** @const */ helper

Here is a completely random (useless except for demo) example of @const helper at work with advanced optimizations:

/** @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');

compiles to: alert((void 0).getElementsByTagName("body")[0]+"New user"+(void 0).getElementsByTagName("body")[0]);

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

The benefit of this is that the code will still work during development without having to preprocess it before each run. (with the added benefit of better optimization)

为你拒绝所有暧昧 2024-12-10 17:19:38

在现代,它看起来像是 RequireJS 或等效 AMD 模块的工作。
所有其他答案都讨论了预编译和缩小——这很好,应该另外考虑。

In modern times, it looks like a job for RequireJS or equivalent AMD module.
All of the other answers talk about precompilation and minification - which are good, and should be considered in addition.

满身野味 2024-12-10 17:19:38

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

Its not possible to use Preprocessor or #define function inside JavaScript... JavaScript is loosly coupled and interpreted language..... But you can use this in Typescript as it is Strongly coupled and uses compiler...

只是我以为 2024-12-10 17:19:38

如果使用像 apache 这样的 Web 服务器(以及用于本地开发的 XAMPP),请使用 PHP 作为预处理器。只需将扩展名从 .js 更改为 .php,然后插入任意数量(包括零)的 PHP 标签即可。

If using a web server like apache (and XAMPP for local development), use PHP as your preprocessor. Simply change extensions from .js to .php, and insert any number (including zero) of PHP tags.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文