基于AScript的JavaScript脚本语言发布啦

AScript是一个开源的C#动态脚本解析执行引擎,支持扩展多种脚本语言,2026年7月14日正式发布了js脚本语言AScript.Lang.JavaScript,快来试试吧!

一、介绍

支持JavaScript基础语法和数据类型,以及数组、集合、字典、对象操作。

支持require引用模块。

二、安装

复制代码
1 install-package AScript
2 install-package AScript.Lang.JavaScript

三、使用说明

1、注册语言

复制代码
1 Script.Langs.Set("js", JavaScriptLang.Instance);
2 // 可全局设置为默认语言
3 // Script.Langs.Set("js", JavaScriptLang.Instance, setDefault: true);

2、定义函数

复制代码
 1 var s = @"
 2 function sum(a,b) {
 3     return a+b;
 4 }
 5 sum(10,20)
 6 ";
 7 var script = new Script();
 8 script.Context.Langs = new [] { "js" };
 9 var result = script.Eval(s);
10 Assert.AreEqual(30L, result);

3、正则表达式

js中使用 /{pattern}/{options} 格式表示正则表达式。

复制代码
1 var script = new Script();
2 script.Context.Langs = new[] { "js" };
3 var result = script.Eval<List<object>>("'hello world World'.match(/world/gi)");
4 Assert.AreEqual(2, result.Count);
5 Assert.AreEqual("world", result[0]);
6 Assert.AreEqual("World", result[1]);

4、解构

1)对象解构:支持默认值、别名、嵌套解构。

复制代码
1 var s = @"
2 var {name, age} = {name: 'Alice', age: 25}; // name='Alice', age=25
3 var {a, b = 100} = {a: 10}; // a=10, b=100
4 var {inner: {name}} = {inner: {name: 'Tom', age: 20}}; // name='Tom'
5 var {name: aliasName} = {name: 'Bob'}; // aliasName='Bob'
6 ";
7 var script = new Script();
8 script.Context.Langs = new[] { "js" };
9 script.Eval(s);

2)数组解构:支持默认值、嵌套解构

复制代码
1 var s = @"
2 var [x, y, z] = [10, 20, 30]; // x=10, y=20, z=30
3 var [x, , z] = [1, 2, 3]; // x=1, z=3
4 var [a = 5, b = 10] = [3]; // a=3, b=10
5 var [[inner], outer] = [[10], 20]; // inner=10, outer=20
6 ";
7 var script = new Script();
8 script.Context.Langs = new[] { "js" };
9 script.Eval(s);

3)混合解构:对象、数组混合解构

复制代码
1 var script = new Script();
2 script.Context.Langs = new[] { "js" };
3 script.Eval("var [first, {name}] = [1, {name: 'John'}]");
4 Assert.AreEqual(1L, script.Eval("first"));
5 Assert.AreEqual("John", script.Eval("name"));

5、字符串插值

复制代码
1 var s = @"
2 var name='tom'; 
3 `hello ${name}, 5+8=${5+8}`
4 ";
5 var script = new Script();
6 script.Context.Langs = new [] { "js" };
7 Assert.AreEqual("hello tom, 5+8=13", script.Eval(s));

6、字符串函数

复制代码
 1 String.fromCharCode(65,66,67); // 'ABC'
 2 'hello'.startsWith('he'); // true
 3 'hello'.endsWith('a'); // false
 4 'hello'.includes('e'); // true
 5 'hello'.indexOf('el'); // 1
 6 'hello'.indexOf('el', 2); // -1
 7 'hello'.lastIndexOf('l'); // 3
 8 'hello'.search('el'); // 1
 9 'hello'.search(/el/gi); // 1
10 'hello'.substr(-2); // 'lo'
11 'hello'.substr(-2,1); // 'l'
12 'hello'.substring(2); // 'llo'
13 'hello'.substring(2,4); // 'll'
14 'hello'.slice(2); // 'llo'
15 'hello'.slice(2,4); // 'll'
16 'hello'.slice(-3); // 'llo'
17 'hello'.slice(-3,-1); // 'll'
18 'Hello'.toLowerCase(); // 'hello'
19 'Hello'.toUpperCase(); // 'HELLO'
20 ' hello '.trim(); // 'hello'
21 ' hello '.trimStart(); // 'hello '
22 ' hello '.trimEnd(); // ' hello'
23 'hello'.padStart(7); // '  hello'
24 'hello'.padStart(7, 'x'); // 'xxhello'
25 'hello'.padEnd(7); // 'hello  '
26 'hello'.padEnd(7, 'x'); // 'helloxx'
27 'hello'.charAt(1); // 'e'
28 'hello'.charCodeAt(1); // 101L
29 'hello tom, I am Tony'.match('to'); // ['to']
30 'hello tom, I am Tony'.match(/to/); // ['to']
31 'hello tom, I am Tony'.match(/to/gi); // ['to', 'To']
32 'hello tom, I am Tony'.replace('to', 'x'); // 替换第1项:'hello xm, I am Tony'
33 'hello tom, I am Tony'.replaceAll('to', 'x'); // 替换所有项(区分大小写):'hello xm, I am Tony'
34 'hello tom, I am Tony'.replace(/to/g, 'x'); // 替换匹配项:'hello xm, I am Tony'
35 'hello tom, I am Tony'.replace(/to/gi, 'x'); // 替换匹配项:'hello xm, I am xny'
36 'a,b,c'.split(','); // ['a','b','c']
37 'hello'.repeat(2); // 'hellohello'
38 'hello'.concat(' ', 'world'); // 'hello world'

7、创建数组

对应C#中的List<object>类型。

复制代码
 1 var s = @"
 2 var arr1 = [1,2,3];
 3 var arr2 = new Array(1,2,3);
 4 var arr3 = new Array(2);
 5 ";
 6 var script = new Script();
 7 script.Context.Langs = new[] { "js" };
 8 script.Eval(s);
 9 var arr1 = script.Eval<List<object>>("arr1");
10 Assert.AreEqual(3, arr1.Count);
11 Assert.AreEqual(1L, arr1[0]);
12 Assert.AreEqual(2L, arr1[1]);
13 Assert.AreEqual(3L, arr1[2]);
14 var arr3 = script.Eval<List<object>>("arr3");
15 Assert.AreEqual(2, arr3.Count);
16 Assert.IsNull(arr3[0]);
17 Assert.IsNull(arr3[1]);

8、数组函数

复制代码
 1 [1, 2].concat([3, 4]); // [1, 2, 3, 4]
 2 [1, 2, 3].join(','); // '1,2,3'
 3 [1, 2, 3].indexOf(2); // 1
 4 [1, 2, 3].includes(2); // true
 5 [1, 2, 3].reverse(); // [3, 2, 1]
 6 [1, 2, 3, 4, 5].filter(x => x % 2 == 0); // [2, 4]
 7 [1, 2, 3].map(x => x * 2); // [2, 4, 6]
 8 [1, 2, 3].reduce((acc, x) => acc + x); // 6
 9 [1, 2, 3].reduce((acc, x) => acc + x, 10); // 16
10 [2, 4, 6].every(x => x % 2 == 0); // true
11 [1, 3, 5].some(x => x % 2 == 0); // false
12 [1, 2, 3].find(x => x > 1); // 2
13 [1, 2, 3].findIndex(x => x > 1); // 1
14 [1, 2, 3].fill(0); // [0, 0, 0]
15 [1, 2, 3].forEach(x => { }); // 遍历数组
16 [1, 2, 3].pop(); // 3
17 [1, 2, 3].push(5, 6, 7); // 数组结尾处理添加元素
18 [1, 2, 3].shift(); // 移除并返回首部元素
19 [1, 2, 3].unshift(5, 9, 10); // 从首部插入3个元素
20 [1, 2, 3, 4, 5].slice(2, 4); // 截取列表[2,4):[3, 4]
21 [1, 2, 3, 4, 5].splice(1, 2); // 截取并返回列表:[2, 3]

9、时间Date

对应C#中的DateTime类型。

复制代码
 1 new Date(); // 当前时间
 2 Date.now(); // 当前时间戳
 3 new Date(2026, 6, 4); // 2026-07-04
 4 var time = new Date('2026-7-4');
 5 time.getYear(); // 获取年份-1900:126
 6 time.getMonth(); // 获取月份-1:6
 7 time.getDate(); // 获取月份中的天(1~31):4
 8 time.getDay(); // 获取星期:6
 9 time.getHours();
10 time.getMinutes();
11 time.getSeconds();
12 time.getMilliseconds();
13 time.getTime(); // 获取时间戳
14 time.toString('yyyy-MM-dd'); // '2026-07-04'
15 time.setFullYear(2025);
16 time.setFullYear(2025, 6);
17 time.setFullYear(2025, 6, 4);
18 time.setHours(21);
19 time.setMinutes(36);
20 time.setSeconds(15);
21 time.setMilliseconds(238);

10、字典Map

对应C#中的Dictionary<object, object>类型。

复制代码
 1 var m = new Map([['a', 1], ['b', 2], ['c', 3]]);
 2 m.set('d', 4);
 3 m.size; // 4
 4 m.get('a'); // 1
 5 m.has('a'); // true
 6 m.delete('c');
 7 m.clear();
 8 m.keys();
 9 m.values();
10 m.entries();
11 m.forEach(function(value, key) { });

11、集合Set

对应C#中的HashSet<object>类型。

复制代码
1 var set = new Set([1, 2, 3]);
2 set.add(4);
3 set.has(2);
4 set.delete(3);
5 set.clear();
6 set.size;
7 set.forEach(x => { });

12、Promise

js异步编程,对应C#中的Task<object>。

  • then/catch/finally
复制代码
1 var script = new Script();
2 script.Context.Langs = new[] { "js" };
3 var result = script.Eval("await new Promise((resolve, reject) => resolve(1)).then(x => x + 1).catch(err=>{})");
4 Assert.AreEqual(2L, result);
  • Promise.all
复制代码
1 var s = @"
2 var arr = await Promise.all([Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)]);
3 arr[0] + arr[1] + arr[2]
4 ";
5 var script = new Script();
6 script.Context.Langs = new[] { "js" };
7 var result = script.Eval(s);
8 Assert.AreEqual(6L, result);
  • Promise.any
复制代码
1 var script = new Script();
2 script.Context.Langs = new[] { "js" };
3 var result = script.Eval<long>("await Promise.any([Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)])");
4 Assert.AreEqual(1L, result);

13、数学函数

复制代码
 1 Math.abs(-5); // 5
 2 Math.acos(0.5);
 3 Math.acosh(2);
 4 Math.asin(0.5);
 5 Math.asinh(2);
 6 Math.atan(1);
 7 Math.atan2(1, 1);
 8 Math.atanh(0.5);
 9 Math.tan(0);
10 Math.tanh(0);
11 Math.sign(5);
12 Math.sin(0);
13 Math.sinh(0);
14 Math.cbrt(27);
15 Math.ceil(5.1);
16 Math.clz32(1);
17 Math.cos(0);
18 Math.cosh(0);
19 Math.exp(1);
20 Math.expm1(1);
21 Math.floor(5.9); // 5.0
22 Math.fround(5.5);
23 Math.hypot(3, 4);
24 Math.imul(2, 3);
25 Math.log(1);
26 Math.log10(100);
27 Math.log1p(1);
28 Math.log2(8);
29 Math.max(1, 10, 5); // 10.0
30 Math.min(1, 10, 5); // 1.0
31 Math.pow(2, 3); // 8.0
32 Math.random(); // [0,1)
33 Math.round(5.4); // 5.0
34 Math.sqrt(4); // 2.0
35 Math.pow(3, 2); // 9.0
36 Math.trunc(5.9); // 5.0
37 Math.E;
38 Math.PI;
39 Math.SQRT2;
40 Math.SQRT1_2;
41 Math.LN2;
42 Math.LN10;
43 Math.LOG2E;
44 Math.LOG10E;

14、setTimeout/clearTimeout

复制代码
 1 string code = @"
 2 var result = 0;
 3 function onTimeout(a, b) {
 4 result = a + b;
 5 }
 6 var handle = setTimeout(onTimeout, 50, 10, 20);
 7 handle;
 8 ";
 9 var script = new Script();
10 script.Context.Langs = new[] { "js" };
11 script.Eval<object>(code);
12 Thread.Sleep(100);
13 Assert.AreEqual(30L, script.Eval("result"));

15、setInterval/clearInterval

复制代码
 1 string code = @"
 2 var count = 0;
 3 function handler() { count = 1; }
 4 var timer = setInterval(handler, 40);
 5 timer;
 6 ";
 7 var script = new Script();
 8 script.Context.Langs = new[] { "js" };
 9 var timerObj = script.Eval<object>(code);
10 Thread.Sleep(70);
11 script.Eval("clearInterval(timer)");
12 Assert.AreEqual(1L, script.Eval("count"));

16、if条件

支持对象检测,null/undefined/0/false/空字符串为false,其他值为true。

复制代码
 1 string code = @"
 2 var n = 15;
 3 var result = '';
 4 if (n < 10) {
 5     result = 'less than 10';
 6 } else if (n < 20) {
 7     result = 'less than 20';
 8 } else {
 9     result = '20 or more';
10 }
11 result;
12 ";
13 var script = new Script();
14 script.Context.Langs = new[] { "js" };
15 Assert.AreEqual("less than 20", script.Eval(code));

17、for循环

循环中支持 continue/break/return 控制。

复制代码
 1 string code = @"
 2 var sum = 0;
 3 for (var i = 0; i < 5; i++) {
 4     sum += i;
 5 }
 6 sum;
 7 ";
 8 var script = new Script();
 9 script.Context.Langs = new[] { "js" };
10 Assert.AreEqual(10L, script.Eval(code));

18、for of遍历值

循环中支持 continue/break/return 控制。

复制代码
 1 string code = @"
 2 var list = ['tom', 'jim', 'john'];
 3 var s = '';
 4 for(var item of list) {
 5     s += item + ',';
 6 }
 7 s
 8 ";
 9 var script = new Script();
10 script.Context.Langs = new[] { "js" };
11 Assert.AreEqual("tom,jim,john,", script.Eval(code));

19、for in遍历数组或集合

循环中支持 continue/break/return 控制。

复制代码
 1 string code = @"
 2 var list = ['tom', 'jim', 'john'];
 3 var s = '';
 4 for(var i in list) {
 5     s += list[i] + ',';
 6 }
 7 s
 8 ";
 9 var script = new Script();
10 script.Context.Langs = new[] { "js" };
11 Assert.AreEqual("tom,jim,john,", script.Eval(code));

20、for in遍历对象或字典

循环中支持 continue/break/return 控制。

复制代码
 1 string code = @"
 2 var person = { 'name': 'Bob', age: 25 };
 3 var s = '';
 4 for(var key in person) {
 5     s += key + ':' + person[key] + ',';
 6 }
 7 s
 8 ";
 9 var script = new Script();
10 script.Context.Langs = new[] { "js" };
11 Assert.AreEqual("name:Bob,age:25,", script.Eval(code));

21、while循环

循环中支持 continue/break/return 控制。

复制代码
 1 string code = @"
 2 var i = 0;
 3 var sum = 0;
 4 while (i < 5) {
 5     sum += i;
 6     i++;
 7 }
 8 sum;
 9 ";
10 var script = new Script();
11 script.Context.Langs = new[] { "js" };
12 Assert.AreEqual(10L, script.Eval(code));

22、require引用模块

使用require引用模块并返回模块实例,如: var fs = require('fs') 。

如果父级上下文环境或者所在语言环境已引用相同模块,则不会重复安装模块,直接返回该模块实例。

四、fs文件模块

注:服务端项目请谨慎添加文件模块,避免脚本中恶意删除、修改文件。

1)安装nuget包

复制代码
install-package AScript.Lang.JavaScript.fs

2)添加fs模块

复制代码
JavaScriptLang.Instance.AddModule("fs", new JavaScriptFileSystemModule());

3)同步读写文件

复制代码
1 string s = @"
2 var fs = require('fs');
3 fs.writeFileSync('test.txt', 'hello world', 'utf-8');
4 fs.readFileSync('test.txt', 'utf-8')
5 ";
6 var script = new Script();
7 script.Context.Langs = new[] { "js" };
8 var result = script.Eval(s);
9 Assert.AreEqual("hello world", result);

4)异步读写文件

复制代码
1 string s = @"
2 var fs = require('fs');
3 await fs.writeFile('test.txt', 'async write', 'utf-8');
4 await fs.readFile('test.txt', 'utf-8')
5 ";
6 var script = new Script();
7 script.Context.Langs = new[] { "js" };
8 var result = await script.EvalAsync<string>(s);
9 Assert.AreEqual("async content", result);

5)其他方法

复制代码
 1 var fs = require('fs');
 2 fs.appendFileSync('test.txt', 'append content', 'utf-8'); // 同步追加文件
 3 fs.appendFile('test.txt', 'append context', 'utf-8'); // 异步追加文件
 4 fs.copyFileSync('test.txt', 'test_copy.txt'); // 同步拷贝文件
 5 fs.copyFile('test.txt', 'test_copy.txt'); // 异步拷贝文件
 6 fs.unlinkSync('test.txt'); // 同步删除文件
 7 fs.unlink('test.txt'); // 异步删除文件
 8 var reader = fs.createReadStream('test.txt'); // 读文件流
 9 var writer = fs.createWriteStream('test2.txt'); // 写文件流
10 reader.pipe(writer); // 读取文件流并写入目标文件流
11 // 读文件流事件:open/data/error/end/close
12 reader.on('data', function(chunk) {
13     console.log(chunk);
14 });
15 reader.on('end', function() {
16     console.log('end');
17 });
18 // 写文件流事件:open/error/finish/close
19 writer.on('open', ()=>console.log('open'));
20 writer.on('close', ()=>console.log('close'));
21 writer.write('hello');
22 writer.end();

五、axios模块

1)安装nuget包

复制代码
install-package AScript.Lang.JavaScript.axios

2)添加axios模块

复制代码
JavaScriptLang.Instance.AddModule("axios", new JavaScriptAxiosModule());

3)get

复制代码
1 string s = @"
2 var axios = require('axios');
3 await axios.get('http://test.com/api/user/list'); 
4 ";
5 var script = new Script();
6 script.Context.Langs = new[] { "js" };
7 var result = script.Eval<dynamic>(s);
8 var data = result.data;

4)post

复制代码
1 string s = @"
2 var axios = require('axios');
3 await axios.post('http://test.com/api/user/update', {code:'123',name:'tom'}); 
4 ";
5 var script = new Script();
6 script.Context.Langs = new[] { "js" };
7 var result = script.Eval<dynamic>(s);
8 var data = result.data;

5)其他方法

复制代码
 1 var axios = require('axios');
 2 var instance = axios.create({baseURL:'http://test.com'});
 3 instance.get('/api/user/list')
 4     .then(res=>{})
 5     .catch(err=>{});
 6 instance.post('/api/user/update', {code:'123',name:'tom'})
 7     .then(res=>{})
 8     .catch(err=>{});
 9 instance.put('/api/user', {});
10 instance.delete('/api/user', {});
11 // mock
12 var mockInstance = axios.createMock([{code:'123',name:'tom'}, {code:'124',name:'john'}]);
13 var resp = await mockInstance.get('http://test.com/api/user/list'); // resp.data: [{code:'123',name:'tom'}, {code:'124',name:'john'}]

六、结束语

C#中执行JavaScript脚本有很多开源库,比如Microsoft.ClearScript、Jint、Jurassic等,大家常用哪个脚本引擎呢?不妨试试AScript.Lang.JavaScript引擎。

AScript开源地址:https://gitee.com/rockey627/AScript

相关推荐
LuoCore1 小时前
AForge.Video.FFMPEG.dll加载失败解决指南
c#
kyriewen2 小时前
我看完这篇安全论文——AI推荐的npm包,92%是编出来的
前端·javascript·ai编程
吴可可1232 小时前
C#元组解构实现变量交换
c#
心中有国也有家2 小时前
AtomGit Flutter 鸿蒙客户端:Canvas 绘制进阶-路径、渐变与混合模式
android·javascript·flutter·华为·harmonyos
鹿目4 小时前
使用 Vant CLI 搭建 UI 组件库:从 H5 到小程序跨平台
前端·javascript
默_笙4 小时前
😭 我花了两小时找了一个数据结构 bug,才把"迷你 Cursor"跑起来,绝望(bushi)
前端·javascript
竹林8184 小时前
wagmi v2 监听合约事件踩坑记:从 `useContractEvent` 到 `watchContractEvent`,我重构了三版才搞定实时数据流
前端·javascript
Java面试题总结4 小时前
LeetCode 93.复原IP地址
算法·leetcode·职场和发展·.net
xingcheng5 小时前
Vue 2 + JavaScript编码规范skill
javascript