大家好,很高兴又见面了,我是" 高级前端进阶 ",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!
1.什么是 Jint
Jint 是 .NET 的 Javascript 解释器,可以在任何现代 .NET 平台上运行,支持 .NET Standard 2.0 和 .NET 4.6.2 目标(及更高版本)。在性能方面,Jint 也是非常优秀:
Jint 可以适应以下典型场景:
Jint 的一些用户包括 RavenDB、EventStore、OrchardCore、ELSA Workflows、docfx、JavaScript Engine Switcher 等等。
目前 Jint 在 Github 通过 BSD-2-Clause 协议开源,有超过 3.7k 的 star,1k 的 fork、1.7k 的项目依赖量,是一个值得关注的开源项目。
2.如何使用 Jint
基础示例
下面示例定义了一个名为 log 的新值,该值指向 Console.WriteLine,然后运行一个调用 log('Hello World!') 的脚本。
var engine = new Engine() .SetValue("log", new Action<object>(Console.WriteLine));engine.Execute(@" function hello() { log('Hello World'); }; hello();");
变量 x 设置为 3,并且 x * x 在 JavaScript 中计算。结果直接返回到 .NET,在本例中为双精度值 9。
var square = new Engine() .SetValue("x", 3) // define a new variable .Evaluate("x * x") // evaluate a statement .ToObject(); // converts the value to .NET
还可以直接传递 POCO 或匿名对象并从 JavaScript 使用。例如,在此示例中,一个新的 Person 实例是通过 JavaScript 操作的。
var p = new Person { Name = "Mickey Mouse"};var engine = new Engine() .SetValue("p", p) .Execute("p.Name ='Minnie'");Assert.AreEqual("Minnie", p.Name);
可以调用 JavaScript 函数引用:
var add = new Engine() .Execute("function add(a, b) { return a + b; }") .GetValue("add");add.Invoke(1, 2); // -> 3
或者通过函数名称调用:
var engine = new Engine() .Execute("function add(a, b) { return a + b; }");engine.Invoke("add", 1, 2); // -> 3
访问 .NET 程序集和类
开发者可以通过如下配置引擎实例来允许引擎访问任何 .NET 类:
var engine = new Engine(cfg => cfg.AllowClr());
然后就可以将系统命名空间作为全局值进行访问。以下是它在命令行实用程序上下文中的使用方式:
jint> var file = new System.IO.StreamWriter('log.txt');jint> file.WriteLine('Hello World !');jint> file.Dispose();
国际化
如果不想使用计算机的默认值,则可以在使用区域设置 JavaScript 方法时强制引擎应使用的时区或文化,下面示例强制将时区设置为太平洋标准时间。
var PST = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");var engine = new Engine(cfg => cfg.LocalTimeZone(PST));engine.Execute("new Date().toString()"); // Wed Dec 31 1969 16:00:00 GMT-08:00
下面示例使用法语作为默认区域性:
var FR = CultureInfo.GetCultureInfo("fr-FR");var engine = new Engine(cfg => cfg.Culture(FR));engine.Execute("new Number(1.23).toString()"); // 1.23engine.Execute("new Number(1.23).toLocaleString()"); // 1,23
使用模块
可以使用模块从多个脚本文件导入和导出变量:
var engine = new Engine(options =>{ options.EnableModules(@"C:\Scripts");})var ns = engine.Modules.Import("./my-module.js");var value = ns.Get("value").AsString();
默认情况下,模块解析算法将仅限于 EnableModules 中指定的基本路径,并且没有包支持。但是,开发者可以通过两种方式提供自己的包。 使用 JavaScript 源代码定义模块:
engine.Modules.Add("user", "export const name ='John';");var ns = engine.Modules.Import("user");var name = ns.Get("name").AsString();
或者使用模块构建器定义模块,其允许从 .NET 导出 CLR 类和值:
// Create the module 'lib' with the class My class and the variable versionengine.Modules.Add("lib", builder => builder .ExportType<My class>() .ExportValue("version", 15));// Create a user-defined module and do something with 'lib'engine.Modules.Add("custom", @" import {My class, version} from 'lib'; const x = new My class(); export const result as x.doSomething();");// Import the user-defined module; this will execute the import chainvar ns = engine.Modules.Import("custom");// The result contains "live" bindings to the modulevar id = ns.Get("result").AsInteger();
3.Jint 的安全性
以下功能为开发者提供了一个安全的沙盒环境来运行用户脚本:
4.本文总结
本文主要和大家介绍 Jint ,其是 .NET 的 Javascript 解释器,可以在任何现代 .NET 平台上运行,支持 .NET Standard 2.0 和 .NET 4.6.2 目标(及更高版本)。因为篇幅问题,关于 Jint 主题只是做了一个简短的介绍,但是文末的参考资料提供了大量优秀文档以供学习,如果有兴趣可以自行阅读。如果大家有什么疑问欢迎在评论区留言。
参考资料
https://github.com/sebastienros/jint
https://blog.devgenius.io/a-javascript-rules-engine-in-net-6-fb092cdc44c
https://github.com/topics/jint