Hello World
Spiga

服务器端执行JavaScript代码

2010-11-09 18:11 by 老赵, 17754 visits

话说,如今不在客户端使用JavaScript代码才是稀奇事儿。由于Web应用的体验越来越丰富,客户端用JavaScript实现的逻辑也越来越多,这造成的结果就是某些几乎一致的逻辑需要在客户端和服务器端各实现一遍。这违反了DRY原则,不容易维护。幸运的是,我们可以在服务器端执行JavaScript代码,谁让JavaScript傍上了这无比霸道的浏览器平台呢?

例如,如今在客户端使用JavaScript进行验证已经是个标准,它可以有效避免用户在正常情况下提交错误的数据,增强用户体验。当然,服务器端的验证是必不可少的,因为这才是“安全性”的体现。有些解决方案,会在服务器端提供有限的验证种类,然后在客户端生成JavaScript代码,并辅以服务器端的验证框架。这种做法可以追溯到ASP.NET 1.x上的Validator控件,但这显然会有扩展性,灵活性上的限制,因此我更倾向于在服务器端执行JavaScript代码。

例如,要检查用户名是否合法,我们可能会写这样的JavaScript代码:

var checkName = function (name) { return /^\w{3,10}$/.test(name); }

这在客户端验证自然没有任何问题,服务器端就要借助一些JavaScript执行引擎了。在.NET平台上有例如比较新的IronJS项目,这是个基于DLR的JavaScript执行引擎,十分重视性能,从作者博客上的评测结果来看,甚至领先于以速度见长的V8。可惜的是,IronJS还没有完整实现ECMAScript 3.0,还缺少一些重要功能,例如正则表达式。

Jint是一个.NET平台上较早的JavaScript执行引擎,因此与DLR关系不大,因此可能不太容易与IronPython,IronRuby等语言进行互操作。用它来执行一些简单的JavaScript脚本不成问题,例如上面的代码:

var jint = new Jint.JintEngine();
jint.Run(@"var checkName = function(name) { return /^\w{3,10}$/.test(name); }");

Console.WriteLine(jint.CallFunction("checkName", "jeffz")); // True
Console.WriteLine(jint.CallFunction("checkName", "hello world")); // False

只可惜,在实际使用中,Jint不支持多线程的环境,即我们无法在多个线程下同时调用jint的CallFunction方法,但是如果每次都重新Run一遍JavaScript代码,也会带来较多的性能开销。其实要解决这个问题也并不困难,构造一个对象池即可,.NET 4中提供了并行容器(如ConcurrentStack,ConcurrentQueue),实现一个简单的对象池可谓不费吹灰之力。

这方面Jurassic的表现要好的多,这是一个构建于.NET 4.0的JavaScript执行引擎:

var engine = new Jurassic.ScriptEngine();
engine.Evaluate(@"var checkName = function(name) { return /^\w{3,10}$/.test(name); }");

Console.WriteLine(engine.CallGlobalFunction<bool>("checkName", "jeffz"));
Console.WriteLine(engine.CallGlobalFunction<bool>("checkName", "hello world"));

此外,从Benchmark上来看,Jurassic性能也比Jint有所提高,但还是远远落后于V8,甚至IE 8里的JavaScript引擎。而且,它还提供了一个基于Silverlight控制台,您可以在浏览器里把玩一番。

令人感到意外的是,Jint和Jurassic作为JavaScript执行引擎都有一些严重的问题,那便是不能正确运行showdown.js(JavaScript实现的Markdown转化器)——虽然我并没有发现showdown.js中有过于复杂的内容,基本就是些字符串操作吧。原本我还想把它们用在mono中,既然如此也就不做进一步尝试了。不过,经过简单的实验,Jurassic似乎使用了mono 2.8中尚不支持的接口,但也有可能只是Jurassic控制台中的问题。

有趣的是,.NET平台下最靠谱的JavaScript执行引擎居然是Rhino JavaScript,最近一次发布是在2009年3月,不过实现的十分完整。要说缺点,可能就是使用起来比较麻烦,还有,这是个Java项目。

嗯,我没有开玩笑,我们完全可以在.NET平台下使用Rhino JavaScript:

var cx = Context.enter();
try
{
    var scope = cx.initStandardObjects();
    cx.evaluateString(scope, @"var checkName = function(name) { return /^\w{3,10}$/.test(name); }", "checkName.js", 1, null);
    var func = (Function)scope.get("checkName", scope);

    Console.WriteLine(Context.toString(func.call(cx, scope, scope, "jeffz")));
    Console.WriteLine(Context.toString(func.call(cx, scope, scope, "hello world"));
}
finally 
{
    Context.exit();
}

因为我们有IKVM.NET。mono等.NET开源社区上有大量宝藏,就看您能利用多少了。我用ikvmc把js.jar转化为RhinoJs.dll之后就可以直接使用,效果很好,对调试也有很好的支持(如果JavaScript执行时出现了错误,则VS会直接带您至出错的那行)。性能也是比较令人满意的,在我的Mac OSX上安装的Ubuntu Server 10.10虚拟机,单线程转化并过滤博客上最近的3800条评论,大约耗时20秒。试验时Host上还开着一个Windows 7虚拟机,还有大量浏览器等应用程序,并不十分空闲。

您可能知道,我的博客目前是基于mono 2.6的,其中比较有特色的地方便是评论功能了,我使用Markdown标记,并提供了实时的预览功能,这自然需要在客户端解释Markdown标记,并进行过滤。目前,我还在服务器使用了C#实现的Markdown转化器及过滤逻辑,但在某些特殊情况下结果会有所不同,且需要维护两套代码。不久以后,我会将把博客升级为ASP.NET 4.0及mono 2.8(C# 4.0的dynamic特性在某些情况下的确比较方便),并且在服务器端使用IKVM.NET + Rhino JavaScript执行相同转化代码。从效果上来看还是十分令人满意的。

值得一提的是,其实在.NET平台上还有一个基于DLR的JavaScript执行引擎,是为RemObjects Script for .NET,据称也支持mono。只可惜它并不是开源产品(不过公开了源代码),且授权协议要求我们最多在5台机器上安装代码,且只供我们自己使用,于是我就没有对它有关注太多了。

Creative Commons License

本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名赵劼(包含链接),具体操作方式可参考此处。如您有任何疑问或者授权方面的协商,请给我留言

Add your comment

62 条回复

  1. 链接

    will 2010-11-09 18:58:50

    这些对应MVC里面的数据验证有些帮助,比用MVC自带的那个灵活多了。

  2. 链接

    小城故事 2010-11-09 20:31:54

    老赵精力真充沛,看这么多开源项目。我想,JavaScript的问题,以后会关系Html5和Silverlight成败。

  3. Benjamin
    220.248.45.*
    链接

    Benjamin 2010-11-09 20:32:19

    这个很强大。如果客户端JavaScript引用JS类库了,那么服务端是不是每次执行都要把JS类库包括进来呢?

  4. Benjamin
    220.248.45.*
    链接

    Benjamin 2010-11-09 20:36:15

    再问老赵一个无关的问题:Introduction to Algorithms第二版的中文版算法导论翻译的如何呢?国内会不会引进第三版影印的呢?

  5. 老赵
    admin
    链接

    老赵 2010-11-09 21:25:29

    @Benjamin

    一般都是创建一个Engine,Run/Evaluate一些JavaScript代码,然后反复调用同一个方法的。我这里强调了“在多线程下”能否使用,就是这个原因。

    算法导论的翻译质量我就不清楚了……

  6. 链接

    陈梓瀚(vczh) 2010-11-10 10:15:28

    @Benjamin

    1. 不要老是下载同样的东西是浏览器的责任哈
    2. 看影印版吧,翻译太囧了
  7. 链接

    Ivony 2010-11-10 13:48:11

    其实一直觉得把JavaScript搬到服务器来意义不是很大。就最上面的那个例子,我们能很简单的翻译成C#:

    Func<string, bool> checkeName = value => Regex.IsMatch( @"^\w{3,10}$", value, RegexOptions.ECMAScript);
    

    甚至于,我可以把这个C#翻译成JavaScript,这似乎要比实现一个语言引擎要简单的多。

    Expression<Func<string, bool>> checkeName = value => Regex.IsMatch( @"^\w{3,10}$", value, RegexOptions.ECMAScript);
    

    或者说我可以更简单的用:

    public UsernameValidator : RegularExpressionValidator
    {
      protected override string Pattern { get { return @"^\w{3,10}$"; } }
    }
    

    这样的代码来描述需求,然后我会自动生成客户端和服务器端的验证,这并不难,因为马上就能看到了。

    那么在验证方面,麻烦的事情还是怎么去操纵HTML得到我们想要的效果。尤其是怎样让客户端验证和服务器端验证得到一致的效果(对于某些客户端无法完成的验证)。这一点Validator控件做的不错,但WebForm实在不讨人喜欢。

    从类库能力来说,C#大于JavaScript,C#能干的绝大多数事情JavaScript不一定能简单高效的完成。所以,让C#获得JavaScript的能力或者从C#生成JavaScript会是更靠谱的事情不是么?

  8. anonymous
    118.96.84.*
    链接

    anonymous 2010-11-10 14:04:52

    http://www.slideshare.net/jeffz/why-java-sucks-and-c-rocks-final

    that was great, I'd like to hear from u more, but sadly u don't blog in english :(

  9. 链接

    Ivony 2010-11-10 14:07:57

    看来老赵要开双语博了。

  10. 老赵
    admin
    链接

    老赵 2010-11-10 14:32:53

    @Ivony

    我举的例子毕竟简单嘛,复杂的验证,例如带点if/else什么的,就不容易从C#生成JavaScript了。而且我最后也谈起个我的使用场景,就是Markdown标记的转换和过滤。其实如果有个成熟的C#生成JavaScript,或者让JavaScript执行C#代码的方案,倒也是不错的,可惜现状就是“谁弱听谁的”,“能者多劳”……

  11. 老赵
    admin
    链接

    老赵 2010-11-10 14:33:20

    Ivony: 看来老赵要开双语博了。

    开过,废弃了,实在太累了……

  12. Duron800
    207.46.92.*
    链接

    Duron800 2010-11-10 14:49:52

    它可以有效避免用户在正常情况下提交正确的数据,增强用户体验。

  13. Duron800
    207.46.92.*
    链接

    Duron800 2010-11-10 15:04:29

    @anonymous

    Read his Chinese blog.

  14. 链接

    tuablove 2010-11-10 17:44:04

    严重关注,我找这个找很久了,最好能找到支持.net,mono,silverlight的,这样项目很多东西都能支持! 我现在用的Microsoft.JScript,Microsoft.Vsa,但是在批量数据下效率还是很差! 现在在这篇文章里提到了,IronJS,Jint,Jurassic,Rhino JavaScript,RemObjects Script for .NET,赵姐夫能不能搞点详细的测试,尤其是调用时的效率大比拼!

  15. 链接

    tuablove 2010-11-10 17:47:24

    雪中送炭啊,雪中送炭啊,忍不住再赞一个! 不过,赵哥,ironjs 怎么用啊,我只找到了个他给的f#调用的例子,有c#使用的例子嘛,或者文档!

  16. 老赵
    admin
    链接

    老赵 2010-11-10 20:24:50

    @tuablove

    自己试一下吧,IronJS现在实现的其实还很不完整,不妨跳过。

  17. 链接

    tuablove 2010-11-10 20:49:18

    IronJS实在没有找到doc,没找到demo,所有的文章都是说有这么个东西,就完事!放弃! 于是刚试了Jurassic,发现

    var engine = new Jurassic.ScriptEngine();
    engine.Evaluate("var test = function(p) { return p.X; }");
    var p=new Point() { X = 100, Y = 11 };                
    var a3= engine.CallGlobalFunction("test", p);
    

    报错,返回类型也非常麻烦,仅限于几种,放弃!

  18. 链接

    tuablove 2010-11-10 23:34:18

    找到了无数好用的Java的JavaScript Engine,果然是JavaScript啊,.net在这方面太欠缺了。总结一下各个Script Engine:

    • IronJS 不会用,不知道怎么用(C#)
    • Jint 3.5 版效率太低
    • Jint 4.0 报错
    • Jurassic 无法传自定义class
    • Rhino JavaScript 要装kvm 大概看了下15M
    • RemObjects Script for .NET 已经免费 但是仍需要验证

    都是大概看了一下,拿来就简单测试,没具体研究!

  19. 老赵
    admin
    链接

    老赵 2010-11-11 00:16:28

    @tuablove

    JavaScript和Java的关系,就像雷锋和雷峰塔一样。话说如果你只是在Windows下用,不妨就用Microsoft.JScript吧。还有,如果你是服务器端程序,我想15M的IKVM应该也不算什么的吧。

    还有,除了Rhino以外,还有哪些Java的JavaScript引擎比较好?

  20. 链接

    tuablove 2010-11-11 09:59:37

    赵哥看看spidermonkey-dotnet,我还没搞明白

  21. 链接

    Rain 2010-11-11 13:40:17

    偶像,我来了。 :)

  22. 老赵
    admin
    链接

    老赵 2010-11-11 17:05:59

    @tuablove

    好像是通过p/invoke来调用spidermonkey引擎,不是托管代码写的。

  23. 链接

    tuablove 2010-11-12 09:33:07

    能测试的都测试了一遍,都没有Microsoft.JScript高效,Microsoft.JScript比c#也就慢了70倍左右,其他的都慢的离谱!几百上千倍,大大的影响了效率。

    不过Microsoft.JScript只能c# call js,但在js里不能调c#方法,很有不足,而且Microsoft.JScript被微软干掉了,会有警告提示。

    我就想不明白,为啥微软总是干掉好用的,弄点不实际的东西,就像silverlight,悲剧了,现在跑来搞html5,连w3c都说html5现在标准还没有定制完全!微软着急个什么劲啊,再说了,ie9又不支持vista以下操作系统,就这点,没个5年搞不定,鲍尔默脑子坏掉了。

    不知道有没有高手把Microsoft.JScript里的东西扒出来,再加上js里调用c#方法?

  24. 掌握星光
    114.250.163.*
    链接

    掌握星光 2010-11-12 11:35:30

    这样使用js是否会影响浏览器缓存?

  25. 老赵
    admin
    链接

    老赵 2010-11-12 17:06:34

    @掌握星光: 这样使用js是否会影响浏览器缓存?

    你没看懂文章啊。

  26. 链接

    Ivony 2010-11-13 14:36:38

    ASP服务器端的jscript引擎就是WSH(Windows脚本宿主)的吧,也就是IE9以前IE用的JS引擎。。。。

  27. 链接

    Ivony 2010-11-13 14:52:27

    话说如果WSH能有.NET接口的话,也是蛮不错的,不知道有没。

  28. mathgl
    113.12.168.*
    链接

    mathgl 2010-11-14 15:51:20

    @老赵

    IKVM是挺不错。。之前我有个服务应用的版本是4.0之前 还没有concurrentdictionary.于是直接用java的concurrenthashmap..效果还挺好...

    不过遗憾的是 转换memcached client基本上用不了...

  29. 老赵
    admin
    链接

    老赵 2010-11-14 16:02:14

    @mathgl

    是嘛,出什么问题啊?我之前试过Java的MongoDB驱动和Lucene,似乎还都很正常。我以为这种普通的基于IO的类库是最靠谱的,最不容易的是那些动态性强的,涉及大量JVM特性的,例如Rhino这种的。

  30. 掌握星光
    114.250.163.*
    链接

    掌握星光 2010-11-15 10:04:48

    汗,原来你是想吧客户端的js文件读出来放到服务器端运行。 不知道像jquery这样的类库的插件能否运行,如果能运行倒是不错。 要运行的话是否需要先把jquery加载进去在加载他的插件吗?

  31. 老赵
    admin
    链接

    老赵 2010-11-15 10:22:17

    @掌握星光: 要运行的话是否需要先把jquery加载进去在加载他的插件吗?

    哎,我觉得你问这些问题,说明你对于很多简单的东西的理解还很混乱……

    其实现在连IronJS都可以执行jQuery了。不过问题还是在于,jQuery所依赖的很多DOM API,它不是JavaScript的一部分,所以我不知道在服务器端执行jQuery有什么意义。

  32. 掌握星光
    114.250.163.*
    链接

    掌握星光 2010-11-15 10:43:23

    并非简单的东西理解的很乱,你这个文章的意思无非是把某些代码写两个版本不利于维护。

    但实际情况在于:在很多项目中,至少我们公司的全部项目中Javascript=jquery,当然还有很多其他出色的类库

    Jquery之类的类库实在是太方便了,他们在javascript的基础上实现,但javascript离开他们已经不行了,就算不用现有的也得先自己开发一个,除非愿意写很多基本的代码。

    真正脱离各种各样类库的js代码有多少?

    像验证这种情况要不我依赖客户端的验证框架,要不我在客户端只检查下必须填写的有没有填,其他的像填写的正不正确统统发到服务器端处理。

    $("form").submit(function() {
        inputs = $("#table_edit").find(".required :input").removeClass("error");
        empty = inputs.filter(function() {
            return $(this).val().replace(/\s*/g, '') == '';
        });
        if (empty.length) {
            alert("您有些必须填写的内容没有填写,请检查。");
            empty.addClass("error");
            return false;
        }
        else {
            $(this).ajaxSubmit(options);
            return false;
        }
    });
    
    function showResponse(data) {
        if (data.State == true) {
            $("#SaveBut").attr("disabled", false);
            ReLoadAndClose();
        }
        else {
            $("#SaveBut").attr("disabled", false);
            alert(data.Message);
        }
    }
    

    就好像这样,需要填写的没填写的标红,然后直接提交,服务器处理好了直接回发一个json文本处理就行了。

  33. 掌握星光
    114.250.163.*
    链接

    掌握星光 2010-11-15 10:44:34

    需要在服务器端执行的js代码实在不多,我是没搞清楚你这么做有什么意义,汗。

  34. 老赵
    admin
    链接

    老赵 2010-11-15 13:59:20

    @掌握星光

    在服务器端需要执行的JS代码是不多,但是还是会带来重复维护,说到底就是和JavaScript上面重复的逻辑,比如过滤HTML中的XSS内容。你说的这些我都明白,这都是最正常不过的做法,和我说的一点冲突都没有。而且,我的建议和倾向是写一点独立于jQuery的代码,然后和jQuery粘结到一起,也是很简单的,复用性更好。

    如果你真觉得你的代码离不开jQuery,那就在服务器端加载它。你刚才问,“要运行的话是否需要先把jquery加载进去在加载他的插件吗?”,这答案难道还不够明显么……所以我会觉得你理解的混乱,因为我觉得如果理解正确了,就没有什么问题,这篇文章其实说的实在太简单了,呵呵。

  35. 掌握星光
    114.250.163.*
    链接

    掌握星光 2010-11-15 14:19:01

    汗,你说的那些我都没用过,一是我比较土,很多东西没接触过,另外也从来没往那方面考虑过,没这个需求,纯属没话找话,失态失态。

  36. apoclast
    174.34.143.*
    链接

    apoclast 2010-11-18 13:44:46

    说道.NET 4.0和Mono, 老赵, 我最近在一台linux服务器上搭建了Mono2.8, 是下载源码后直接用它的附带的shell脚本编译的, 结果这台服务器上只能运行.NET 2.0运行时的程序, 而.NET 4.0(Visual Studio 2010自己编译的)则会说无法支持程序要求的运行时, 改用默认运行时2.0 老赵遇到过此类情况吗?

  37. 老赵
    admin
    链接

    老赵 2010-11-18 18:51:06

    @apoclast

    没有遇到过,这个是mono程序会自己判断的吧。

  38. oldest
    182.48.112.*
    链接

    oldest 2010-11-25 15:32:36

    老赵能否介绍一下,IKVM+Rhino能达到怎样的能力?能做到从C#访问JS中的对象、从JS访问C#中的对象吗?数据类型、类如何兼容?

  39. earthengine
    112.213.186.*
    链接

    earthengine 2010-11-26 07:55:51

    我遇到一个奇怪的问题,老赵帮忙看一下。

    我尝试手工组装一个Expression tree, 实现可以尾递归化的阶乘函数,递归用Y组合子实现。

    delegate Func<T, R> SFunc<T, R>(SFunc<T, R> i);
    delegate Func<T, R> TFunc<T, R>(Func<T, R> i);
    delegate T TFunc<T>(T i);
    delegate Func<T, R> YFunc<T, R>(TFunc<T, R> i);
    delegate YFunc<T, R> SYFunc<T, R>(SYFunc<T, R> i);
    

    以上定义了用到的一些委托类型

    static Expression<Func<T, R>> ExpressionAbstractor<T, R>(Expression body)
    {
        var p = Expression.Parameter(typeof(T));
        var inv = Expression.Invoke(body, p);
        return Expression.Lambda<Func<T, R>>(inv, p);
    }
    

    这个函数用来把现有的Expression抽象一层,这在实现递归的时候是必要的,此外,从除了LambdaExpression之外的Expression生成LambdaExpression时也要用到它。

    static Expression<YFunc<T, R>> YCombinator<T, R>()
    {
        var _0 = Expression.Parameter(typeof(SFunc<T, R>));
        var _1 = Expression.Parameter(typeof(TFunc<T, R>));
        var e = Expression.Invoke(_1, Expression.Invoke(_0, _0));
        var e1 = Expression.Lambda<SFunc<T, R>>(ExpressionAbstractor<T, R>(e), _0);
        var e2 = Expression.Lambda<SFunc<T, R>>(e, _0);
        var e3 = Expression.Invoke(e2, e1);
        return Expression.Lambda<YFunc<T, R>>(i3, _1);
    }
    

    这个函数返回Y组合子的Expression。留意其中定义e1,e2和e3的那几行,就是这几行似乎有毛病。

    var Y = YCombinator<int, Func<int, int>>();
    
    Expression<TFunc<int, Func<int, int>>> facbody = _ => acc => n => n <= 1 ? acc : _(acc * n)(n - 1);
    Expression<Func<int, int>> fac = ExpressionAbstractor<int, int>(Expression.Invoke(
        Expression.Invoke(Y, facbody), Expression.Constant(1, typeof(int))));
    

    以上是在Main函数里定义的fac函数表达式。 默认情况下LambdaExpression的TailCall属性是关闭的。我写了一个简单的ExpressionVisitor来把它打开

    class UpdateTailCall : ExpressionVisitor
    {
        protected override Expression VisitLambda<T>(Expression<T> node)
        {
            return Expression.Lambda<T>(base.Visit(node.Body), false,
                from p in node.Parameters
                select (ParameterExpression)base.Visit(p));
        }
    }
    

    在测试中发现奇怪的现象是:

    1. 以上表达式树,无论tailcall打开与否,都可以运行。
    2. 如果把e3的定义改成

    这样

    var e3 = Expression.Invoke(e1, e1);
    

    就必须把tailcall打开才能运行,否则会抛出一个奇怪的VerificationException异常。

    当然,e3 = Expression.Invoke(e2, e2)是不可行的,会堆栈溢出,这个可以理解。但VerificationException异常是怎么回事呢?

  40. earthengine
    112.213.186.*
    链接

    earthengine 2010-11-26 08:02:49

    上个帖子里,那个ExpressionVisitor里面第二个调用参数应该是true。出现这个错误是因为在实验的时候我要排除tailcall这个因素,结果发现,无论是否tailcall,只要调用visit后的函数,就能运行,否则就异常。这让问题变得更奇怪了。

  41. 书痕
    110.194.98.*
    链接

    书痕 2010-11-28 15:13:02

    看了标题,我以为赵老师要谈NodeJs,呵呵!

  42. 老赵
    admin
    链接

    老赵 2010-11-28 20:19:19

    @书痕

    NodeJS不是JavaScript引擎,是利用V8的一个服务器通信框架/类库。

  43. GuangXiN
    123.125.1.*
    链接

    GuangXiN 2010-11-29 04:52:05

    可惜的是,IronJS还没有完整实现ECMAScript 3.0,还缺少一些重要功能,例如正则表达式。

    这个,汗,没有正则表达式的服务器端js能干什么?

  44. edie
    120.199.4.*
    链接

    edie 2010-11-29 18:45:21

    我不太喜欢花哨的东西。 c#干什么还是去干什么,js干什么还是去干什么什么。 与其用c#去做js的事情,我还是宁可写两份代码。

  45. 老赵
    admin
    链接

    老赵 2010-11-29 19:36:48

    @edie

    等其他某个人的生产力比你高一大半的时候,不知道你还是不是“宁可”写两份代码,呵呵。

  46. xin
    119.132.16.*
    链接

    xin 2010-12-09 11:07:00

    @老赵

    我想问一下你博客里面鼠标放在代码上就能打印是怎么做的?万分感谢

  47. tudouxigua
    124.74.45.*
    链接

    tudouxigua 2010-12-09 15:16:25

    在服务器端执行javascript应该还是有使用的地方,比如说爬虫,一些网站为了防止爬虫,主要内容是使用js载入的,这个时候服务器的js执行就有用武之地了。

  48. 老赵
    admin
    链接

    老赵 2010-12-09 15:20:48

    @tudoucigua

    我用的是Syntax Highlighter。

  49. nyth
    124.114.66.*
    链接

    nyth 2010-12-16 15:54:31

    赵哥,你的文章,我看着有点吃力!

  50. Paul
    218.186.10.*
    链接

    Paul 2010-12-29 15:49:50

    I have fixed the problem you noticed with Jurassic and showdown.js. Basically it uses the non-standard RegExp.$1 syntax, which I have now added to Jurassic. Thanks for reporting this problem!

    本人有固定的问题,你与侏罗系和showdown.js注意。基本上它使用非标准RegExp.$1语法,这是我现在被添加到侏罗纪。感谢您报告此问题!

  51. mathgl
    125.215.206.*
    链接

    mathgl 2011-01-03 02:50:56

    @apoclast: 说道.NET 4.0和Mono, 老赵, 我最近在一台linux服务器上搭建了Mono2.8, 是下载源码后直接用它的附带的shell脚本编译的, 结果这台服务器上只能运行.NET 2.0运行时的程序, 而.NET 4.0(Visual Studio 2010自己编译的)则会说无法支持程序要求的运行时, 改用默认运行时2.0 老赵遇到过此类情况吗?

    这个问题我曾经碰到过..经验是你把相关的源码在linux下重新编译一次看看..

    mono的编译器有好几个版本, gcs, dmcs, mcs等。默认是 4.0 mode.你可以切换一下看看能不能编译..

    我的经验是:现在.net 4.0下的程序 不一定100% 都能直接在mono 2.8.x下用。哪怕程序都是依赖标准库...

  52. 老赵
    admin
    链接

    老赵 2011-01-03 09:06:03

    @mathgl

    库的问题也是有别于运行时吧,他说的是运行时问题。

  53. 助平君
    205.156.160.*
    链接

    助平君 2011-01-13 12:33:27

    我也在考虑这个问题很久了,看到这篇博文也给了我很多启发。

    前端和后端要维护相同的(验证)代码真的非常低效,而且容易遗漏某部分的维护(顾此失彼的事情并不少见)。而且一个少复杂的验证可能会有几十行代码,属性之间的依赖、联系等验证也不是简单的正则表达式所能够完成的。为了解决这个问题,有几种可行的方式。

    • 由C#代码生成JavaScript代码 (e.g. Script#)
    • 远程调用由服务端实现的验证代码 (e.g. Restful Web Services)
    • 本文提到的方式

    多谢分享。

  54. wq522595
    183.62.146.*
    链接

    wq522595 2011-06-22 17:17:03

    mark down

  55. 像小强一样活着
    219.238.253.*
    链接

    像小强一样活着 2011-09-14 13:28:19

    @老赵

    想请教下使用Rhino JavaScript,需要安装KVM还是IKVM?又如何配置呢?

  56. 百世
    112.225.229.*
    链接

    百世 2012-11-21 16:51:08

    执行转换后的Rhino JavaScript,感觉C#会很耗资源,在执行的时候会发现CPU和内存瞬间飙升!

  57. 老赵
    admin
    链接

    老赵 2012-11-21 17:02:18

    @百世

    看你执行什么东西了,我执行的东西效率效率巨高。

  58. 半夜十二点
    211.91.223.*
    链接

    半夜十二点 2013-09-05 00:41:39

    老赵,我做了个爬虫,用Jurassic去爬网上的js, 但是这些js中有window,document等浏览器中的js原始对象, Jurassic碰到这些就会提示未定义, 有没什么办法能让Jurassic识别,或者有没那种定义好了的js原始对象库?

  59. 上海装潢公司
    114.95.135.*
    链接

    上海装潢公司 2016-12-10 17:20:59

    失散18年后相认上海装饰公司 男子猥亵殴打女子上海装潢公司 2017节假日安排松江装潢公司 铝厂向黄河排污九亭装潢公司 外卖员强奸案告破上海松江装潢公司 持枪杀人逃12年松江装修公司 赴美嫁网友遭毒打泗泾装潢公司 协警遭狱警鄙视洞泾装潢公司 偷窥如厕反被拍松江装饰公司 阿富汗击毙塔利班上海松江装修公司 曝昆凌录节目呕吐上海装潢

    十大幸福城市出炉九亭装修公司 为偶像直播间炫富九亭装饰公司 老人赚骗子51万泗泾装饰公司 诺基亚手机回归洞泾装修公司 偷6只蓝孔雀吃掉洞泾装饰公司 去厕所需挂如厕牌洞泾办公室装潢 邓超被错认彭于晏公司装潢松江

    男童输血染艾滋新凯家园装潢公司 老人赚骗子51万润江花苑装潢公司 山东失联女已遇害同润菲诗艾伦装潢公司 杨利伟回应敲击声上海装潢设计公司 禁忌浪漫爱情电影《无法触碰的爱》上海装修设计公司 奥朗德宣布不连任上海装修公司 科长被情人举报上海装饰设计公司 曝陈妍希提前当妈同润菲诗艾伦装修公司 高院判聂树斌无罪同润菲诗艾伦装饰公司 孪生姐妹捐遗体金港花园装潢公司 北京公交起火冒烟佘山装潢公司 男学生求婚女老师松江办公室装修公司 退学后烧炭自杀松江厂房装修公司 特朗普提太空政策松江装潢设计公司 校长见证情侣表白漕河泾办公室装修 偷得Note7竟自燃漕河泾厂房装修 打537次110被拘漕河泾装潢公司 落井男童遗体找到漕河泾装饰公司

    新凯家园装修公司 西安约500名直播主播被欠薪 经纪人疑携款潜逃新凯家园装饰公司 润江花苑装修公司 润江花苑装饰公司 金港花园装修公司 金港花园装饰公司 员工被罚当众吃虫佘山装饰公司 北京公交起火冒烟佘山装潢公司 渔民捕到神秘龙虾洞泾办公室装修 宁泽涛奥运前遭罚漕河泾装修公司

已自动隐藏某些不合适的评论内容(主题无关,争吵谩骂,装疯卖傻等等),如需阅读,请准备好眼药水并点此登陆后查看(如登陆后仍无法浏览请留言告知)。

发表回复

登录 / 登录并记住我 ,登陆后便可删除或修改已发表的评论 (请注意保留评论内容)

昵称:(必填)

邮箱:(必填,仅用于Gavatar

主页:(可选)

评论内容(大于5个字符):

  1. Your Name yyyy-MM-dd HH:mm:ss

使用Live Messenger联系我