您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > javascript

跨端轻量JavaScript引擎的实现与探索

时间:2024-03-12 14:08:07  来源:  作者:京东云开发者

一、JAVAScript

 

1.JavaScript语言

JavaScript是ECMAScript的实现,由ECMA 39(欧洲计算机制造商协会39号技术委员会)负责制定ECMAScript标准。

ECMAScript发展史:

 

2.JavaScript引擎

JavaScript引擎是指用于处理以及执行JavaScript脚本的虚拟机。

常见的JavaScript引擎:

3.JavaScript引擎工作原理

a.V8引擎工作原理

b.Turbofan技术实例说明

function sum(a, b) {

return a + b;

}

这里a和b可以是任意类型数据,当执行sum函数时,Ignition解释器会检查a和b的数据类型,并相应地执行加法或者连接字符串的操作。

如果 sum函数被调用多次,每次执行时都要检查参数的数据类型是很浪费时间的。此时TurboFan就出场了。它会分析函数的执行信息,如果以前每次调用sum函数时传递的参数类型都是数字,那么TurboFan就预设sum的参数类型是数字类型,然后将其编译为机器码。

但是如果某一次的调用传入的参数不再是数字时,表示TurboFan的假设是错误的,此时优化编译生成的机器代码就不能再使用了,于是就需要进行回退到字节码的操作。

三、QuickJS

1.QuickJS作者简介

法布里斯·貝拉 (Fabrice Bellard)

2.QuickJS简介

QuickJS 是一个小型的嵌入式 Javascript 引擎。 它支持 ES2023 规范,包括模块、异步生成器、代理和 BigInt。

它可以选择支持数学扩展,例如大十进制浮点数 (BigDecimal)、大二进制浮点数 (BigFloat) 和运算符重载。

•小且易于嵌入:只需几个 C 文件,无外部依赖项,一个简单的 hello world 程序的 210 KiB x86 代码。

•启动时间极短的快速解释器:在台式 PC 的单核上运行 ECMAScript 测试套件的 76000 次测试只需不到 2 分钟。 运行时实例的完整生命周期在不到 300 微秒的时间内完成。

•几乎完整的 ES2023 支持,包括模块、异步生成器和完整的附录 B 支持(旧版 Web 兼容性)。

•通过了近 100% 的 ECMAScript 测试套件测试: Test262 Report(https://test262.fyi/#)。

•可以将 Javascript 源代码编译为可执行文件,无需外部依赖。

•使用引用计数(以减少内存使用并具有确定性行为)和循环删除的垃圾收集。

•数学扩展:BigDecimal、BigFloat、运算符重载、bigint 模式、数学模式。

•用 Javascript 实现的带有上下文着色的命令行解释器。

•带有 C 库包装器的小型内置标准库。

3.QuickJS工程简介

5.94MB quickjs

├── 17.6kB cutils.c /// 辅助函数

├── 7.58kB cutils.h /// 辅助函数

├── 241kB libbf.c /// BigFloat相关

├── 17.9kB libbf.h /// BigFloat相关

├── 2.25kB libregexp-opcode.h /// 正则表达式操作符

├── 82.3kB libregexp.c /// 正则表达式相关

├── 3.26kB libregexp.h /// 正则表达式相关

├── 3.09kB list.h /// 链表实现

├── 16.7kB qjs.c /// QuickJS stand alone interpreter

├── 22kB qjsc.c /// QuickJS command line compiler

├── 73.1kB qjscalc.js /// 数学计算器

├── 7.97kB quickjs-atom.h /// 定义了javascript中的关键字

├── 114kB quickjs-libc.c

├── 2.57kB quickjs-libc.h /// C API

├── 15.9kB quickjs-opcode.h /// 字节码操作符定义

├── 1.81MB quickjs.c

├── 41.9kB quickjs.h /// QuickJS Engine

├── 49.8kB repl.js /// REPL

├── 218kB libunicode-table.h /// unicode相关

├── 53kB libunicode.c /// unicode相关

├── 3.86kB libunicode.h /// unicode相关

├── 86.4kB unicode_gen.c /// unicode相关

└── 6.99kB unicode_gen_def.h /// unicode相关

4.QuickJS工作原理

QuickJS的解释器是基于栈的。

QuickJS的对byte-code会优化两次,通过一个简单例子看看QuickJS的字节码与优化器的输出,以及执行过程。

function sum(a, b) {

return a + b;

}

•第一阶段(未经过优化的字节码)

;; function sum(a, b) {

enter_scope 1

;; return a + b;

line_num 2

scope_get_var a,1 ///通用的获取变量的指令

scope_get_var b,1

add

return

;; }

•第二阶段

;; function sum(a, b) {

;; return a + b;

line_num 2

get_arg 0: a /// 获取参数列表中的变量

get_arg 1: b

add

return

;; }

•第三阶段

;; function sum(a, b) {

;; return a + b;

get_arg0 0: a /// 精简成获取参数列表中第0个参数

get_arg1 1: b

add

return

;; }

sum(1,2);

通过上述简单的函数调用,观察sum函数调用过程中栈帧的变化,通过计算可知sum函数最栈帧大小为两个字节

get_arg0

get_arg1

add

return

1

2

3

将栈顶的数据3返回

1

5.内存管理

QuickJS通过引用计算来管理内存,在使用C API时需要根据不同API的说明手动增加或者减少引用计数器。

对于循环引用的对象,QuickJS通过临时减引用保存到临时数组中的方法来判断相互引用的对象是否可以回收。

6.QuickJS简单使用

Github上clone完最新的源码后,通过执行(macos 环境)以下代码即可在本地安装好qjs、qjsc、qjscalc几个命令行程序

sudo make

sudo make install

qjs: JavaScript代码解释器

qjsc: JavaScript代码编译器

qjscalc: 基于QuickJS的REPL计算器程序

通过使用qjs可以直接运行一个JavaScript源码,通过qsjc的如下命令,则可以输出一个带有byte-code源码的可直接运行的C源文件:

qjsc -e -o add.c examples/add.js

#include "quickjs-libc.h"

const uint32_t qjsc_add_size = 135;

const uint8_t qjsc_add[135] = {

0x02, 0x06, 0x06, 0x73, 0x75, 0x6d, 0x0e, 0x63,

0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x06, 0x6c,

0x6f, 0x67, 0x1e, 0x65, 0x78, 0x61, 0x6d, 0x70,

0x6c, 0x65, 0x73, 0x2f, 0x61, 0x64, 0x64, 0x2e,

0x6a, 0x73, 0x02, 0x61, 0x02, 0x62, 0x0e, 0x00,

0x06, 0x00, 0xa2, 0x01, 0x00, 0x01, 0x00, 0x05,

0x00, 0x01, 0x25, 0x01, 0xa4, 0x01, 0x00, 0x00,

0x00, 0x3f, 0xe3, 0x00, 0x00, 0x00, 0x40, 0xc2,

0x00, 0x40, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x38,

0xe4, 0x00, 0x00, 0x00, 0x42, 0xe5, 0x00, 0x00,

0x00, 0x38, 0xe3, 0x00, 0x00, 0x00, 0xb8, 0xb9,

0xf2, 0x24, 0x01, 0x00, 0xcf, 0x28, 0xcc, 0x03,

0x01, 0x04, 0x1f, 0x00, 0x08, 0x0a, 0x0e, 0x43,

0x06, 0x00, 0xc6, 0x03, 0x02, 0x00, 0x02, 0x02,

0x00, 0x00, 0x04, 0x02, 0xce, 0x03, 0x00, 0x01,

0x00, 0xd0, 0x03, 0x00, 0x01, 0x00, 0xd3, 0xd4,

0x9e, 0x28, 0xcc, 0x03, 0x01, 0x01, 0x03,

};

static JSContext *JS_NewCustomContext(JSRuntime *rt)

{

JSContext *ctx = JS_NewContextRaw(rt);

if (!ctx)

return NULL;

JS_AddIntrinsicBaseobjects(ctx);

JS_AddIntrinsicDate(ctx);

JS_AddIntrinsicEval(ctx);

JS_AddIntrinsicStringNormalize(ctx);

JS_AddIntrinsicRegExp(ctx);

JS_AddIntrinsicJSON(ctx);

JS_AddIntrinsicProxy(ctx);

JS_AddIntrinsicMapSet(ctx);

JS_AddIntrinsicTypedArrays(ctx);

JS_AddIntrinsicPromise(ctx);

JS_AddIntrinsicBigInt(ctx);

return ctx;

}

int mAIn(int argc, char **argv)

{

JSRuntime *rt;

JSContext *ctx;

rt = JS_NewRuntime();

js_std_set_worker_new_context_func(JS_NewCustomContext);

js_std_init_handlers(rt);

JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);

ctx = JS_NewCustomContext(rt);

js_std_add_helpers(ctx, argc, argv);

js_std_eval_binary(ctx, qjsc_add, qjsc_add_size, 0);

js_std_loop(ctx);

js_std_free_handlers(rt);

JS_FreeContext(ctx);

JS_FreeRuntime(rt);

return 0;

}

上面的这个C源文件,通过如下命令即可编译成可执行文件:

gcc add.c -o add_exec -I/usr/local/include quickjs-libc.c quickjs.c cutils.c libbf.c libregexp.c libunicode.c -DCONFIG_BIGNUM

也可以直接使用如下命令,将JavaScript文件直接编译成可执行文件:

qjsc -o add_exec examples/add.js

7.给qjsc添加扩展

QuickJS只实现了最基本的JavaScript能力,同时QuickJS也可以实现能力的扩展,比如给QuickJS添加打开文件并读取文件内容的内容,这样在JavaScript代码中即可通过js代码打开并读取到文件内容了。

通过一个例子来看看添加扩展都需要做哪些操作:

•编写一个C语言的扩展模块

#include "quickjs.h"

#include "cutils.h"

/// js中对应plus函数的C语言函数

static JSValue plusNumbers(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) {

int a, b;

if (JS_ToInt32(ctx, &a, argv[0]))

return JS_EXCEPTION;

if (JS_ToInt32(ctx, &b, argv[1]))

return JS_EXCEPTION;

return JS_NewInt32(ctx, a + b);

}

/// 模块需要导致的列表

static const JSCFunctionListEntry js_my_module_funcs[] = {

JS_CFUNC_DEF("plus", 2, plusNumbers),

};

/// 模块初始化函数,并将plus导出

static int js_my_module_init(JSContext *ctx, JSModuleDef *m) {

return JS_SetModuleExportList(ctx, m, js_my_module_funcs, countof(js_my_module_funcs));

}

JSModuleDef *js_init_module_my_module(JSContext *ctx, const char *module_name) {

JSModuleDef *m;

m = JS_NewCModule(ctx, module_name, js_my_module_init);

if (!m)

return NULL;

JS_AddModuleExportList(ctx, m, js_my_module_funcs, countof(js_my_module_funcs));

return m;

}

•Makefile文件中添加my_module.c模块的编译

QJS_LIB_OBJS= ... $(OBJDIR)/my_module.o

•在qjsc.c文件中注册模块

namelist_add(&cmodule_list,“my_module”,“my_module”,0);

•编写一个my_module.js测试文件

import * as mm from 'my_module';

const value = mm.plus(1, 2);

console.log(`my_module.plus: ${value}`);

•重新编译

sudo make && sudo make install

qjsc -m -o my_module examples/my_module.js /// 这里需要指定my_module模块

最终生成的my_module可执行文件,通过执行my_module输出:

my_module.plus: 3

8.使用C API

在第5个步骤时,生成了add.c文件中实际上已经给出了一个简单的使用C API最基本的代码。当编写一下如下的js源码时,会发现当前的qjsc编译后的可执行文件或者qjs执行这段js代码与我们的预期不符:

function getName() {

return new Promise((resolve, reject) => {

setTimeout(() => {

resolve("张三峰");

}, 2000);

});

}

console.log(`开始执行`);

getName().then(name => console.log(`promise name: ${name}`));

上面的代码并不会按预期的效果输出结果,因为js环境下的loop只执行了一次,任务队列还没有来得急执行程序就结束了,稍微改动一下让程序可以正常输出,如下:

#include <stdio.h>

#include <pthread.h>

#include <stdlib.h>

#include <uv.h>

/* File generated automatically by the QuickJS compiler. */

#include "quickjs-libc.h"

#include <string.h>

static JSContext *JS_NewCustomContext(JSRuntime *rt) {

JSContext *ctx = JS_NewContextRaw(rt);

if (!ctx)

return NULL;

JS_AddIntrinsicBaseObjects(ctx);

JS_AddIntrinsicDate(ctx);

JS_AddIntrinsicEval(ctx);

JS_AddIntrinsicStringNormalize(ctx);

JS_AddIntrinsicRegExp(ctx);

JS_AddIntrinsicJSON(ctx);

JS_AddIntrinsicProxy(ctx);

JS_AddIntrinsicMapSet(ctx);

JS_AddIntrinsicTypedArrays(ctx);

JS_AddIntrinsicPromise(ctx);

JS_AddIntrinsicBigInt(ctx);

return ctx;

}

JSRuntime *rt = NULL;

JSContext *ctx = NULL;

void *run(void *args) {

const char *file_path = "/Volumes/Work/分享/quickjs/code/quickjs/examples/promise.js";

size_t pbuf_len = 0;

js_std_set_worker_new_context_func(JS_NewCustomContext);

js_std_init_handlers(rt);

JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);

ctx = JS_NewCustomContext(rt);

js_std_add_helpers(ctx, 0, NULL);

js_init_module_os(ctx, "test");

const uint8_t *code = js_load_file(ctx, &pbuf_len, file_path);

JSValue js_ret_val = JS_Eval(ctx, (char *)code, pbuf_len, "add", JS_EVAL_TYPE_MODULE);

if(JS_IsError(ctx, js_ret_val) || JS_IsException(js_ret_val)) {

js_std_dump_error(ctx);

}

return NULL;

}

pthread_t quickjs_t;

int main(int argc, char **argv) {

rt = JS_NewRuntime();

pthread_create(&quickjs_t, NULL, run, NULL);

while (1) {

if(ctx) js_std_loop(ctx);

}

js_std_free_handlers(rt);

JS_FreeContext(ctx);

JS_FreeRuntime(rt);

return 0;

}

这样的操作只适合用于测试一下功能,实际生产中使用需要一个即可以在必要的时候调用loop又可以做到不抢占过多的CPU或者只抢占较少的CPU时间片。

四、libuv

1.libuv简价

libuv 是一个使用C语言编写的多平台支持库,专注于异步 I/O。 它主要是为 Node.js 使用而开发的,但 Luvit、Julia、uvloop 等也使用它。

功能亮点

•由 epoll、kqueue、IOCP、事件端口支持的全功能事件循环。

•异步 TCP 和 UDP 套接字

•异步 DNS 解析

•异步文件和文件系统操作

•文件系统事件

•ANSI 转义码控制的 TTY

•具有套接字共享的 IPC,使用 Unix 域套接字或命名管道 (windows)

•子进程

•线程池

•信号处理

•高分辨率时钟

•线程和同步原语

2.libuv运行原理

int uv_run(uv_loop_t* loop, uv_run_mode mode) {

r = uv__loop_alive(loop);

if (!r)

uv__update_time(loop);

while (r != 0 && loop->stop_flag == 0) {

uv__update_time(loop);

uv__run_timers(loop);

ran_pending = uv__run_pending(loop);

uv__run_idle(loop);

uv__run_prepare(loop);

uv__io_poll(loop, timeout);

uv__run_check(loop);

uv__run_closing_handles(loop);

}

}

3.简单使用

static void timer_cb(uv_timer_t *handler) {

printf("timer_cb exec.rn");

}

int main(int argc, const char * argv[]) {

uv_loop_t *loop = uv_default_loop();

uv_timer_t *timer = (uv_timer_t*)malloc(sizeof(uv_timer_t));

uv_timer_init(loop, timer);

uv_timer_start(timer, timer_cb, 2000, 0);

uv_run(loop, UV_RUN_DEFAULT);

}

五、QuickJS + libuv

console.log(`开始执行`);

function getName() {

return new Promise((resolve, reject) => {

setTimeout(() => {

resolve("张三峰");

}, 2000);

});

}

getName().then(name => console.log(`promise name: ${name}`));

#include <stdio.h>

#include <pthread.h>

#include <stdlib.h>

#include <uv.h>

/* File generated automatically by the QuickJS compiler. */

#include "quickjs-libc.h"

#include <string.h>

typedef struct once_timer_data {

JSValue func;

JSValue this_val;

JSContext *ctx;

} once_timer_data;

void once_timer_cb(uv_timer_t *once_timer) {

once_timer_data *data = (once_timer_data *)once_timer->data;

JSContext *ctx = data->ctx;

JSValue js_ret_val = JS_Call(data->ctx, data->func, data->this_val, 0, NULL);

if(JS_IsError(ctx, js_ret_val) || JS_IsException(js_ret_val)) {

js_std_dump_error(ctx);

}

JS_FreeValue(data->ctx, js_ret_val);

JS_FreeValue(data->ctx, data->func);

JS_FreeValue(data->ctx, data->this_val);

free(data);

uv_timer_stop(once_timer);

free(once_timer);

}

void check_cb(uv_check_t *check) {

JSContext *ctx = (JSContext *)check->data;

js_std_loop(ctx);

}

void idle_cb(uv_idle_t *idle) {

}

JSValue set_timeout(JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {

if(argc != 2) return JS_NULL;

JSValue func_val = argv[0];

JSValue delay_val = argv[1];

int64_t delay = 0;

int ret = JS_ToInt64(ctx, &delay, delay_val);

if(ret < 0) js_std_dump_error(ctx);

uv_timer_t *once_timer = (uv_timer_t *)malloc(sizeof(uv_timer_t));

once_timer_data *data = (once_timer_data *)malloc(sizeof(once_timer_data));

data->func = JS_DupValue(ctx, func_val);

data->this_val = JS_DupValue(ctx, this_val);

data->ctx = ctx;

once_timer->data = data;

uv_timer_init(uv_default_loop(), once_timer);

uv_timer_start(once_timer, once_timer_cb, delay, 0);

JSValue js_timer = JS_NewInt64(ctx, (uint64_t)once_timer);

return js_timer;

}

static JSContext *JS_NewCustomContext(JSRuntime *rt) {

JSContext *ctx = JS_NewContextRaw(rt);

if (!ctx)

return NULL;

JS_AddIntrinsicBaseObjects(ctx);

JS_AddIntrinsicDate(ctx);

JS_AddIntrinsicEval(ctx);

JS_AddIntrinsicStringNormalize(ctx);

JS_AddIntrinsicRegExp(ctx);

JS_AddIntrinsicJSON(ctx);

JS_AddIntrinsicProxy(ctx);

JS_AddIntrinsicMapSet(ctx);

JS_AddIntrinsicTypedArrays(ctx);

JS_AddIntrinsicPromise(ctx);

JS_AddIntrinsicBigInt(ctx);

return ctx;

}

void js_job(uv_timer_t *timer) {

JSRuntime *rt = timer->data;

const char *file_path = "/Volumes/Work/分享/quickjs/code/quickjs/examples/promise.js";

size_t pbuf_len = 0;

JSContext *ctx;

js_std_set_worker_new_context_func(JS_NewCustomContext);

js_std_init_handlers(rt);

JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);

ctx = JS_NewCustomContext(rt);

uv_check_t *check = (uv_check_t *)malloc(sizeof(uv_check_t));

uv_check_init(uv_default_loop(), check);

check->data = ctx;

uv_check_start(check, check_cb);

JSValue global = JS_GetGlobalObject(ctx);

JSValue func_val = JS_NewCFunction(ctx, set_timeout, "setTimeout", 1);

JS_SetPropertyStr(ctx, global, "setTimeout", func_val);

JS_FreeValue(ctx, global);

js_std_add_helpers(ctx, 0, NULL);

js_init_module_os(ctx, "test");

const uint8_t *code = js_load_file(ctx, &pbuf_len, file_path);

JSValue js_ret_val = JS_Eval(ctx, (char *)code, pbuf_len, "add", JS_EVAL_TYPE_MODULE);

if(JS_IsError(ctx, js_ret_val) || JS_IsException(js_ret_val)) {

js_std_dump_error(ctx);

}

js_std_free_handlers(rt);

JS_FreeContext(ctx);

}

int main(int argc, char **argv) {

JSRuntime *rt = JS_NewRuntime();

uv_loop_t *loop = uv_default_loop();

uv_timer_t *timer = (uv_timer_t*)malloc(sizeof(uv_timer_t));

timer->data = rt;

uv_timer_init(loop, timer);

uv_timer_start(timer, js_job, 0, 0);

uv_idle_t *idle = (uv_idle_t *)malloc(sizeof(uv_idle_t));

uv_idle_init(loop, idle);

uv_idle_start(idle, idle_cb);

uv_run(loop, UV_RUN_DEFAULT);

JS_FreeRuntime(rt);

return 0;

}



Tags:JavaScript   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除。
▌相关推荐
17 个你需要知道的 JavaScript 优化技巧
你可能一直在使用JavaScript搞开发,但很多时候你可能对它提供的最新功能并不感冒,尽管这些功能在无需编写额外代码的情况下就可以解决你的问题。作为前端开发人员,我们必须了解...【详细内容】
2024-04-03  Search: JavaScript  点击:(0)  评论:(0)  加入收藏
你不可不知的 15 个 JavaScript 小贴士
在掌握如何编写JavaScript代码之后,那么就进阶到实践&mdash;&mdash;如何真正地解决问题。我们需要更改JS代码使其更简单、更易于阅读,因为这样的程序更易于团队成员之间紧密协...【详细内容】
2024-03-21  Search: JavaScript  点击:(21)  评论:(0)  加入收藏
构建一个通用灵活的JavaScript插件系统?看完你也会!
在软件开发中,插件系统为应用程序提供了巨大的灵活性和可扩展性。它们允许开发者在不修改核心代码的情况下扩展和定制应用程序的功能。本文将详细介绍如何构建一个灵活的Java...【详细内容】
2024-03-20  Search: JavaScript  点击:(15)  评论:(0)  加入收藏
对JavaScript代码压缩有什么好处?
对JavaScript代码进行压缩主要带来以下好处: 减小文件大小:通过移除代码中的空白符、换行符、注释,以及缩短变量名等方式,可以显著减小JavaScript文件的大小。这有助于减少网页...【详细内容】
2024-03-13  Search: JavaScript  点击:(0)  评论:(0)  加入收藏
跨端轻量JavaScript引擎的实现与探索
一、JavaScript 1.JavaScript语言JavaScript是ECMAScript的实现,由ECMA 39(欧洲计算机制造商协会39号技术委员会)负责制定ECMAScript标准。ECMAScript发展史: 2.JavaScript...【详细内容】
2024-03-12  Search: JavaScript  点击:(0)  评论:(0)  加入收藏
面向AI工程的五大JavaScript工具
令许多人惊讶的是,一向在Web开发领域中大放异彩的JavaScript在开发使用大语言模型(LLM)的应用程序方面同样大有价值。我们在本文中将介绍面向AI工程的五大工具,并为希望将LLM...【详细内容】
2024-02-06  Search: JavaScript  点击:(49)  评论:(0)  加入收藏
18个JavaScript技巧:编写简洁高效的代码
本文翻译自 18 JavaScript Tips : You Should Know for Clean and Efficient Code,作者:Shefali, 略有删改。在这篇文章中,我将分享18个JavaScript技巧,以及一些你应该知道的示例...【详细内容】
2024-01-30  Search: JavaScript  点击:(64)  评论:(0)  加入收藏
使用 JavaScript 清理我的 200GB iCloud,有了一个意外发现!
本文作者在综合成本因素之下,决定用 Java 脚本来清理一下自己的 iCloud,结果却有了一个意外发现,即在 iCloud 中上传同一个视频和删除此视频之后,iCloud 的空间并不一致,这到底是...【详细内容】
2024-01-11  Search: JavaScript  点击:(96)  评论:(0)  加入收藏
JavaScript前端框架2024年展望
Angular、Next.js、React和Solid的维护者和创作者们展望2024年,分享了他们计划中的改进。译自2024 Predictions by JavaScript Frontend Framework Maintainers,作者 Loraine...【详细内容】
2024-01-05  Search: JavaScript  点击:(84)  评论:(0)  加入收藏
JavaScript开发者转向Rust的原因?
JavaScript开发者转向Rust的原因可能有很多,这里列出一些可能的原因: 性能: Rust是一种编译型语言,其性能通常优于JavaScript等解释型语言。对于需要处理大量数据或需要高并发的...【详细内容】
2024-01-04  Search: JavaScript  点击:(96)  评论:(0)  加入收藏
▌简易百科推荐
17 个你需要知道的 JavaScript 优化技巧
你可能一直在使用JavaScript搞开发,但很多时候你可能对它提供的最新功能并不感冒,尽管这些功能在无需编写额外代码的情况下就可以解决你的问题。作为前端开发人员,我们必须了解...【详细内容】
2024-04-03  前端新世界  微信公众号  Tags:JavaScript   点击:(0)  评论:(0)  加入收藏
你不可不知的 15 个 JavaScript 小贴士
在掌握如何编写JavaScript代码之后,那么就进阶到实践&mdash;&mdash;如何真正地解决问题。我们需要更改JS代码使其更简单、更易于阅读,因为这样的程序更易于团队成员之间紧密协...【详细内容】
2024-03-21  前端新世界  微信公众号  Tags:JavaScript   点击:(21)  评论:(0)  加入收藏
又出新JS运行时了!JS运行时大盘点
Node.js是基于Google V8引擎的JavaScript运行时,以非阻塞I/O和事件驱动架构为特色,实现全栈开发。它跨平台且拥有丰富的生态系统,但也面临安全性、TypeScript支持和性能等挑战...【详细内容】
2024-03-21  前端充电宝  微信公众号  Tags:JS   点击:(19)  评论:(0)  加入收藏
构建一个通用灵活的JavaScript插件系统?看完你也会!
在软件开发中,插件系统为应用程序提供了巨大的灵活性和可扩展性。它们允许开发者在不修改核心代码的情况下扩展和定制应用程序的功能。本文将详细介绍如何构建一个灵活的Java...【详细内容】
2024-03-20  前端历险记  微信公众号  Tags:JavaScript   点击:(15)  评论:(0)  加入收藏
对JavaScript代码压缩有什么好处?
对JavaScript代码进行压缩主要带来以下好处: 减小文件大小:通过移除代码中的空白符、换行符、注释,以及缩短变量名等方式,可以显著减小JavaScript文件的大小。这有助于减少网页...【详细内容】
2024-03-13  WangLiwen    Tags:JavaScript   点击:(0)  评论:(0)  加入收藏
跨端轻量JavaScript引擎的实现与探索
一、JavaScript 1.JavaScript语言JavaScript是ECMAScript的实现,由ECMA 39(欧洲计算机制造商协会39号技术委员会)负责制定ECMAScript标准。ECMAScript发展史: 2.JavaScript...【详细内容】
2024-03-12  京东云开发者    Tags:JavaScript   点击:(0)  评论:(0)  加入收藏
面向AI工程的五大JavaScript工具
令许多人惊讶的是,一向在Web开发领域中大放异彩的JavaScript在开发使用大语言模型(LLM)的应用程序方面同样大有价值。我们在本文中将介绍面向AI工程的五大工具,并为希望将LLM...【详细内容】
2024-02-06    51CTO  Tags:JavaScript   点击:(49)  评论:(0)  加入收藏
JS小知识,使用这6个小技巧,避免过多的使用 if 语句
最近在重构我的代码时,我注意到早期的代码使用了太多的 if 语句,达到了我以前从未见过的程度。这就是为什么我认为分享这些可以帮助我们避免使用过多 if 语句的简单技巧很重要...【详细内容】
2024-01-30  前端达人  今日头条  Tags:JS   点击:(53)  评论:(0)  加入收藏
18个JavaScript技巧:编写简洁高效的代码
本文翻译自 18 JavaScript Tips : You Should Know for Clean and Efficient Code,作者:Shefali, 略有删改。在这篇文章中,我将分享18个JavaScript技巧,以及一些你应该知道的示例...【详细内容】
2024-01-30  南城大前端  微信公众号  Tags:JavaScript   点击:(64)  评论:(0)  加入收藏
使用 JavaScript 清理我的 200GB iCloud,有了一个意外发现!
本文作者在综合成本因素之下,决定用 Java 脚本来清理一下自己的 iCloud,结果却有了一个意外发现,即在 iCloud 中上传同一个视频和删除此视频之后,iCloud 的空间并不一致,这到底是...【详细内容】
2024-01-11    CSDN  Tags:JavaScript   点击:(96)  评论:(0)  加入收藏
站内最新
站内热门
站内头条