本篇译文,删减了原文中一些无关紧要的内容,可以让大家花更少的阅读时间。 原文地址:https://blog.sessionstack.com/how-javascript-works-memory-management-how-to-handle-4-common-memory-leaks-3f28b94cfbec
这篇文章将讨论日常编程中另一个复杂且容易被忽视的问题 — 内存管理。其中还提供了一些关于如何处理 JavaScript 内存泄露的提示,来防止导致内存泄漏以及不会增加我们 WEB 程序的内存消耗。
Overview
像 C 语言这样的底层语言一般都有底层的内存管理接口,比如 malloc()
和 free()
。相反,JavaScript 是在创建变量(对象,字符串等)时自动进行了分配内存,并且在不使用它们时“自动”释放。 释放的过程称为垃圾回收。这个“自动”是混乱的根源,并让 JavaScript(和其他高级语言)开发者错误的感觉他们可以不关心内存管理。
即使使用高级开发语言,开发人员也应该了解内存管理(或至少了解其基础知识)。有时自动内存管理会存在一些问题(如垃圾回收的 bug 和实现限制等)。开发者必须了解相关内存知识才能解决(或找到合适的解决方法,并尽量减少折衷和代码债务)来处理这些问题。
Memory life cycle
无论使用何种编程语言,内存生命周期几乎都是一样的: 以下概述了周期的每个步骤:
Allocate memory — 分配你所需要的内存。程序使用的内存由操作系统分配,在底层语言中(如C语言)这是开发人员需要处理的,在高级语言中由程序自动处理。
Use memory — 使用分配到的内存(读、写)。代码中使用变量对内存进行读、写 操作。
Release memory — 不需要时将其释放/归还。和 Allocate memory 一样,在底层语言中需要开发者自行明确的处理。
What is memory?
讨论 JavaScript 内存之前,我们先简单地讨论一下内存是什么以及它是如何工作的?
在硬件级别上,计算机内存包含大量触发器(flip flops)。每个触发器包含几个晶体管并且能够存储一位(bit)。单个触发器可通过唯一标识符进行寻址,因此我们可以读取和覆盖它们。从概念上讲,我们可以将整个计算机内存视为我们可以读写的一个巨大的位(bit)数组。
因为人类,不善于做一些 bits 的运算和思考,所以将其组织成更大的组来表示数值。8 bits 为 1 byte,超出 byte的,有单词(16bits 或 32bits)
大量的东西存储在内存中,包括:
程序中使用的所有变量以及其他数据
程序代码,以及包括操作系统的代码
虽然编译器和操作系统已经为内存管理做了大量工作,但是还是建议了解一下引擎之下发生了什么。
编译代码时,编译器可以检查原始数据类型,并提前计算它们所需内存。然后将所需的数量分配给调用堆栈中的程序。这些变量分配的空间称为堆栈空间(stack space ),因为函数被调用,它们的内存被添加到现有内存(存储器)的顶部。它们终止时,它们将以LIFO(后进先出)顺序被移除。
int n;
int x[ 4 ] ;
double m;
编译器可以立即计算diam所有内存空间为: 4 + 4 × 4 + 8 = 28 b y t e s 4 + 4 × 4 + 8 = 28 bytes 4 + 4 × 4 + 8 = 2 8 b y t e s
这是现在整数和双精度的工作原理。大约 20 年前,整数通常为 2 字节,双精度为 4 字节。你的代码永远不必依赖于此时基本数据类型的大小。
编译器将插入与操作系统交互的代码,以便在堆栈中请求要存储的变量所需的字节数。
上述示例中,编译器知道每个变量的确切内存地址。实际上,每当我们写入变量时,它就会会内部转为类似”内存地址 4127963“的内容。
注意,如果尝试访问x[4]
,可能会访问到和 m 相关联的数据。这是因为我们访问的元素在数组中并不存在 — 它比数组中最后一个实际分配的元素x[3]
多4个字节,可能会读取(或重写) m 的位。这肯定会对程序产生难以理解的不良影响。 当函数调用其他函数时,每个函数在调用时都会获得自己的堆栈块。它保存所有的局部变量,还有一个程序计数器,可以记录函数的执行位置。当函数执行完成时,其内存块可以再次用于其他目的。
Dynamic allocation
不幸的是,当在编译时不知道变量需要多少内存时,事情就不那么容易了。假设我们想要做类似以下的事情:
int n = readInput ( ) ;
...
这种情况下,在编译时,编译器不知道数组需要多少内存空间,因为其由用户输入的值来确定。
因此,它无法为堆栈上的变量分配空间。相反,我们的程序需要再运行时明确询问操作系统是否有适当的空间。此内存是从堆空间(heap space) 分配的。下述为静态分配和动态分配的差异:
Static allocation
Dynamic allocation
编译时内存大小确定
编译时内存大小不确定
编译阶段执行
运行时执行
分配给栈(stack space)
分配给堆(heap stack)
FILO
没有特定的顺序
Allocation in JavaScript
现在我们将解释第一步(分配内存 — Allocate memory)如何在JavaScript中工作。 JavaScript 使开发人员免于处理内存 — 其在声明时自动完成。
var n = 374 ;
var s = 'sessionstack' ;
var o = {
a: 1 ,
b: null
} ;
var a = [ 1 , null , 'str' ] ;
function f ( a) {
return a + 3 ;
}
someElement. addEventListener ( 'click' , function ( ) {
someElement. style. backgroundColor = 'blue' ;
} , false ) ;
一些函数调用也会导致对象分配:
var d = new Date ( ) ;
var e = document. createElement ( 'div' ) ;
方法可以分配新的值或对象:
var s1 = 'sessionstack' ;
var s2 = s1. substr ( 0 , 3 ) ;
var a1 = [ 'str1' , 'str2' ] ;
var a2 = [ 'str3' , 'str4' ] ;
var a3 = a1. concat ( a2) ;
Using memory in JavaScript
通常在JavaScript中使用内存的过程实际上是对分配内存进行读取与写入的操作。读取与写入可能是写入一个变量或者一个对象的属性值,甚至传递函数的参数。
Release when the memory is not needed anymore
大多数内存管理的问题都在这个阶段。在这里最艰难的任务是找到“哪些被分配的内存确实已经不再需要了”。它往往要求开发人员来确定在程序中哪一块内存不再需要并且释放它。
高级语言解释器嵌入了“垃圾回收器”,它的主要工作是跟踪内存的分配和使用,以便当分配的内存不再使用时,自动释放它。不幸的是,这只能是一个近似的过程,因为要知道是否仍然需要某块内存是无法判定的(无法通过某种算法解决)。
大多数垃圾回收器通过判断内存是否能够被再次访问来工作的,例如:指向它的所有变量都超出了作用域。然而,这只能得到一个近似值。因为在任何一点上,内存位置可能仍然有一个在作用域内指向它的变量,但是它可能将永远不会被再次访问了。
Garbage collection
自动寻找是否一些内存“不再需要”的问题是无法判定的。因此,垃圾回收实现只能有限制的解决一般问题。本节将解释必要的概念,了解主要的垃圾回收算法和它们的局限性。
Memory references
垃圾回收算法依靠的主要概念就是引用(reference) 。 在内存管理的环境中,一个对象如果有访问另一个对象的权限(隐式或者显式),叫做一个对象引用另一个对象。例如,一个Javascript对象具有对它原型的引用(隐式引用)和对它属性的引用(显式引用)。 在这里,“对象”的概念不仅特指 JavaScript 对象,还包括函数作用域(或者全局词法作用域)。
词法作用域定义了如何在嵌套函数中解析变量名称:即使父函数已 return,内部函数也可以包含父函数的作用域。
引用计数垃圾收集 Reference-counting garbage collection
这是最初级的垃圾收集算法。此算法把“对象是否不再需要”简化定义为“对象有没有其他对象引用到它”。如果没有引用指向该对象(零引用),对象将被垃圾回收机制回收。
下述例子,使用了MDN中的例子,而并没有用原文中,因为发现了作者这部分内容完全来自 MDN o(╥﹏╥)o — https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Memory_Management
var o = {
a: {
b: 2
}
} ;
var o2 = o;
o = 1 ;
var oa = o2. a;
o2 = "yo" ;
oa = null ;
Cycles are creating problems
该算法有个限制:无法处理循环引用的事例。在下面的例子中,两个对象被创建,并互相引用,形成了一个循环。它们被调用之后会离开函数作用域,所以它们已经没有用了,可以被回收了。然而,引用计数算法考虑到它们互相都有至少一次引用,所以它们不会被回收。
function f ( ) {
var o1 = { } ;
var o2 = { } ;
o1. p = o2;
o2. p = o1;
}
f ( ) ;
标记-清楚算法 Mark-and-sweep algorithm
这个算法把“对象是否不再需要”简化定义为“对象是否可以获得”。 标记和扫描算法通过以下3个步骤:
根:一般来说,根是在代码中引用的全局变量。例如,在 JavaScript 中,可以充当根的全局变量是“window”对象。Node.js 中的相同对象称为“global”。垃圾收集器构建了所有根的完整列表。;
然后算法检查所有根和它们的孩子并将它们标记为 Active(意思是,它们不是垃圾)。root无法访问的任何内容都将被标记为垃圾。
最后,垃圾收集器释放所有未标记为 Active 的内存块,并将该内存返回给操作系统。
该算法优于“引用计数”算法,因为“一个对象具有零个引用”导致对象不能访问。这与上面循环应用相反。
截止到2012年,所有现代浏览器都提供了标记 - 清除垃圾收集器。在过去几年中,在 JavaScript 垃圾收集(生成/增量/并发/并行垃圾收集)领域所做的所有改进都是该算法的实现改进(mark-and-sweep),但不是对垃圾收集算法本身的改进,也不是决定对象是否可访问的目标。
Cycles are not a problem anymore
在上面的示例中,函数调用返回之后,两个对象从全局对象出发无法获取。因此,他们将会被垃圾回收器回收。 尽管对象之间存在引用,但它们无法从根目录(window)访问。
Counter intuitive behavior of Garbage Collectors
虽然垃圾收集器很方便,但它们还是有自己的权衡取舍。其中之一是非决定论(non-determinism)。换句话说,GC 是不可预测的,无法确定何时会执行收集。这意味着在某些情况下,程序使用的内存要比实际需要的还多。另一个场景是,在特别敏感的应用中,那么一些短暂的暂停会显得特别明显。虽然不确定性意味着回收执行的时间不能被确定,但是大多数 GC 的实现是共享模式 — 在分配内存期间执行回收遍历。如果没有分配执行,大多数 GCs 保持空闲状态。请考虑以下情形:
相当大的一组分配被执行
都被标记为无法访问(假设我们将指向我们不再需要的缓存的引用置空)
没有进一步的分配
在这种情况下,大多数GC不会再运行任何收集动作(passes)。换句话说,即使存在对于收集来说,无法访问的引用,收集器也不会声明这些引用(these are not claimed by the collector)。这些并非严格内存泄漏,但仍导致高于平常的内存使用率。
What are memory leaks?
内存泄漏是应用程序过去使用但后续不再需要,尚未返回操作系统或可用内存池的内存块。 编程语言支持不同的内存管理方式。但是,是否使用某段内存实际上是一个不可判定(undecidable problem)的问题。换句话说,只有开发人员才能明确是否可以将内存返回给操作系统。
某些编程语言提供了帮助开发人员执行此操作的功能,希望开发人员完全明确何时不再使用内存。Wikipedia has good articles on manual and automaticmemory management.
The four types of common JavaScript leaks
1. Global variables
JavaScript 以一种有趣的方式处理未声明的变量:当引用未声明的变量时,会在全局对象中创建一个新变量。在浏览器中,全局对象将是 window,这意味着
function foo ( arg) {
bar = "some text" ;
}
等价于
function foo ( arg) {
window. bar = "some text" ;
}
假设 bar
的目的是仅引用 foo
函数中的变量。但是,如果不使用 var
来声明它,则会创建一个冗余的全局变量。在上述情况下,这不会造成太大伤害。你肯定可以想象一个更具破坏性的场景。
function foo ( ) {
this . var1 = "potential accidental global" ;
}
foo ( ) ;
你可以通过添加 'use strict'
来避免这一切;在 JavaScript 文件的开头,它将打开更严格的解析 JavaScript 模式,以防止意外创建全局变量。
意外的全局变量肯定是个问题,但是,通常情况下,您的代码会被显式的全局变量所侵扰,而这些变量根据定义无法被垃圾收集器收集。需要特别注意用于临时存储和处理大量信息的全局变量。如果必须使用全局变量来存储数据,请确保使用完成后将其指定为null或重新分配它。
2. Timers or callbacks that are forgotten
我们以 setInterval
为例,因为它经常在 JavaScript 中使用.
大多数库都会提供观察者或者其它工具来处理回调函数,在他们自己的实例变为不可访问时,会让回调函数也变为不可访问。不过,下面的代码并不罕见:
var serverData = loadData ( ) ;
setInterval ( function ( ) {
var renderer = document. getElementById ( 'renderer' ) ;
if ( renderer) {
renderer. innerHTML = JSON . stringify ( serverData) ;
}
} , 5000 ) ;
这个例子阐述着 timers 可能发生的情况:计时器会引用不再需要的节点或数据。
renderer
可能在将来会被移除,使得 interval
内的整个块都不再被需要。但是,interval handler
因为 interval
的存活,所以无法被回收(需要停止 interval
,才能回收)。如果 interval handler
无法被回收,则它的依赖也不能被回收。这意味着 serverData
— 可能存储了大量数据,也不能被回收。
在观察者模式下,重要的是在他们不再被需要的时候显式地去删除它们(或者让相关对象变为不可访问)。
幸运的是,大多数现代浏览器都能为您完成这项工作:即使您忘记移除侦听器,一旦观察到的对象无法访问,它们也会自动收集观察者处理程序。在过去,一些浏览器无法处理这些情况(旧的IE6)。
尽管如此,一旦对象变得过时,它仍然符合删除观察者的最佳实践。例如:
var element = document. getElementById ( 'launch-button' ) ;
var counter = 0 ;
function onClick ( event) {
counter++ ;
element. innerHtml = 'text ' + counter;
}
element. addEventListener ( 'click' , onClick) ;
element. removeEventListener ( 'click' , onClick) ;
element. parentNode. removeChild ( element) ;
在使节点无法访问之前,您不再需要调用 removeEventListener
,因为现代浏览器支持可以检测这些循环并适当处理它们的垃圾收集器。
如果利用 jQuery API(其他库和框架也支持它),可以在节点过时之前删除侦听器。即使应用程序在较旧的浏览器版本下运行,该库也将确保没有内存泄漏。
3. Closures
JavaScript 开发的一个关键方面就是闭包:一个可以访问外部(封闭)函数变量的内部函数。由于 JavaScript 运行时的实现细节,可以通过以下方式泄漏内存:
var theThing = null ;
var replaceThing = function ( ) {
var originalThing = theThing;
var unused = function ( ) {
if ( originalThing)
console. log ( "hi" ) ;
} ;
theThing = {
longStr: new Array ( 1000000 ) . join ( '*' ) ,
someMethod: function ( ) {
console. log ( "message" ) ;
}
} ;
} ;
setInterval ( replaceThing, 1000 ) ;
这个代码片段做了一件事:每次调用 replaceThing
时,theThing
都会获得一个新对象,它包含一个大的数组和一个新的闭包(someMethod
)。同时,变量 unused
保留了一个拥有originalThing
引用的闭包(前一次调用 theThing
赋值给了 originalThing
)。已经有点混乱了吗?重要的是,一旦一个作用域被创建为闭包,那么它的父作用域将被共享。
在这个例子中,创建闭包 someMethod
的作用域是于 unused
共享的。unused
拥有 originalThing
的引用。尽管 unused
从来都没有使用,但是 someMethod
能够通过 theThing
在 replaceThing
之外的作用域使用(例如全局范围)。并且由于 someMethod
和 unused
共享闭包作用域,unused
的引用将强制保持 originalThing
处于活动状态(两个闭包之间共享整个作用域),这样防止了垃圾回收。
当这段代码重复执行时,可以观察到内存使用量的稳定增长。当 GC 运行时,也没有变小。实质上,引擎创建了一个闭包的链接列表(root
就是变量 theThing
),并且这些闭包的作用域中每一个都有对大数组的间接引用,导致了相当大的内存泄漏。
This issue was found by the Meteor team and they have a great article that describes the issue in great detail.
4. Out of DOM references
有时候,在数据结构中存储 DOM 结构是有用的。假设要快速更新表中的几行内容。将每行 DOM 的引用存储在字典或数组中可能是有意义的。当这种情况发生时,就会保留同一 DOM 元素的两份引用:一个在 DOM 树中,另一个在字典中。如果将来某个时候你决定要删除这些行,则需要让两个引用都不可达。
var elements = {
button: document. getElementById ( 'button' ) ,
image: document. getElementById ( 'image' )
} ;
function doStuff ( ) {
elements. image. src = 'http://example.com/image_name.png' ;
}
function removeImage ( ) {
document. body. removeChild ( document. getElementById ( 'image' ) ) ;
}
还有一个额外的考虑,当涉及 DOM 树内部或叶子节点的引用时,必须考虑这一点。假设你在 JavaScript 代码中保留了对 table 特定单元格()的引用。有一天,你决定从 DOM 中删除该 table,但扔保留着对该单元格的引用。直观地来看,可以假设 GC 将收集除了该单元格之外所有的内容。实际上,这不会发生的:该单元格是该 table 的子节点,并且 children 保持着对它们 parents 的引用。也就是说,在 JavaScript 代码中对单元格的引用会导致整个表都保留在内存中的。保留 DOM 元素的引用时,需要仔细考虑。
你可能感兴趣的:(JavaScript)
希音(Shein)前端开发面试题集锦和参考答案
大模型大数据攻城狮
arcgis webpack 前端攻击 xss csrf react 前端面试
用Node写过什么工具或npm包在实际开发中,使用Node编写过多种实用工具和npm包。自动化构建工具开发了一个简单的自动化构建工具,用于处理前端项目的资源压缩和合并。在前端项目中,为了优化性能,需要对CSS和JavaScript文件进行压缩,减少文件体积,同时将多个小文件合并成一个大文件,减少HTTP请求。这个工具使用Node的fs模块进行文件的读写操作,通过terser库对JavaScript
【Qt】Qt Widgets和QML(Qt Quick)开发界面的区别
£އއ昔年
qt 开发语言
Qt提供了两种主要的UI技术:QtWidgets和QML(QtQuick)。它们的核心区别主要体现在使用方式、架构、性能、开发难度和适用场景等方面。1.QtWidgetsvs.QML总体对比对比项QtWidgetsQML(QtQuick)语言C++(带QtUI库)QML+JavaScript(底层C++)渲染方式传统窗口系统控件(原生或模拟)基于OpenGL,使用GPU加速UI风格经典桌面UI(W
React 基础教程
阿贾克斯的黎明
前端 react.js 前端 前端框架
目录React基础教程一、React简介二、安装和设置三、创建第一个React组件(一)函数式组件(二)类组件四、渲染组件五、组件的属性和状态(一)属性(Props)(二)状态(State)六、组件的生命周期方法七、事件处理八、总结React是一个用于构建用户界面的JavaScript库。它以高效、灵活和可维护性而受到广泛的欢迎。本教程将介绍React的基础知识,帮助你快速上手React开发。一、
【无标题】Hollo world.Javascript
一一代码
python javascript
HelloWorld最简单JavaScript代码console.log("Hello,World!");变量和数据类型JavaScript中的变量声明和基本数据类型。```javascriptletname="Alice";//字符串constage=25;//数字letisStudent=true;//布尔值console.log(name,age,isStudent);```函数定义一个简单
HTML+CSS+javascript 轮播图
Paula-柒月拾
javascript html css 前端 html5
HTML,CSS和JavaScript可以用来创建轮播图。HTML用于构建网页的结构,所以您可以使用HTML来定义轮播图的各个部分,如图像和文本。CSS用于设计网页的外观,所以您可以使用CSS来设置轮播图的布局和样式。JavaScript用于控制网页的行为,所以您可以使用JavaScript来控制轮播图的功能,如自动播放和用户交互。下面是一个简单的HTMLCSSJavaScript轮播图的例子:H
【2024年华为OD机试】 (C卷,100分)- 分配土地(JavaScript&Java & Python&C/C++)
妄北y
算法汇集笔记总结(保姆级) 华为od c语言 javascript python java
一、问题描述题目描述从前有个村庄,村民们喜欢在各种田地上插上小旗子,旗子上标识了各种不同的数字。某天,集体村民决定将覆盖相同数字的最小矩阵形的土地分配给村里做出巨大贡献的村民。请问此次分配土地,做出贡献的村民最大会分配多大面积?输入描述第一行输入m和n:m代表村子的土地的长。n代表土地的宽。第二行开始输入地图上的具体标识:旗子上的数字为1~500,未插旗子的土地用0标识。输出描述输出此次分配土地,
前端本地储存的方式汇总
懒羊羊我小弟
前端框架 javascript js 浏览器 web app 小程序
JavaScript本地存储是Web开发中用于在客户端存储数据的重要技术,以下是常见方式及其区别和应用场景:一、WEB浏览器本地存储方式及特点1.1储存方式1.Cookie存储容量:约4KB(每个域名)。生命周期:可设置过期时间;默认随会话结束失效。作用域:同源页面共享。访问方式:通过document.cookie读写,每次HTTP请求自动携带。特点:支持服务器端操作(通过HTTP头),但存储效率
【Py/Java/C++/C/JS/Go六种语言OD独家2024E卷真题】20天拿下华为OD笔试之【模拟】2024E-最大相连男生数【欧弟算法】全网注释最详细分类最全的华为OD真题题解
闭着眼睛学算法
最新华为OD真题 # 模拟 # 状态压缩 算法 java c++ c语言 华为od javascript python
可上欧弟OJ系统练习华子OD、大厂真题绿色聊天软件戳oj1441了解算法冲刺训练(备注【CSDN】否则不通过)文章目录相关推荐阅读题目描述与示例题目描述输入描述输出描述示例输入输出解题思路代码代码一:分类写法pythonjavacppCNodejavaScriptGo代码二:合并写法pythonjavacppCNodejavaScriptGo*代码三:状态压缩写法pythonjavacppCNod
【Py/Java/C++/JS/Go五种语言【OD独家2024E卷真题】20天拿下华为OD笔试之【哈希表】2024E-猜字谜【欧弟算法】全网注释最详细分类最全的华为OD真题题解
闭着眼睛学算法
最新华为OD真题 # 哈希表 java c++ 华为od python 算法 leetcode
可上欧弟OJ系统练习华子OD、大厂真题绿色聊天软件戳oj1441了解算法冲刺训练(备注【CSDN】否则不通过)文章目录相关推荐阅读题目描述与示例题目描述输入描述输出描述备注示例一输入输出示例二输入输出解题思路谜面和谜底如何匹配暴力匹配所有谜底谜底库哈希表的构建代码解法一:哈希表预处理谜底pythonjavacppNodejavaScriptgo时空复杂度解法二:暴力匹配解(会超时)pythonja
Visual Studio Code (VSCode) 安装与使用教程
w(゚Д゚)w吓洗宝宝了
vscode ide 编辑器
一、VisualStudioCode简介VisualStudioCode(简称VSCode)是一款由微软开发的轻量级源代码编辑器,支持多种编程语言,如C/C++、Python、JavaScript等。它具有丰富的功能,如代码高亮、智能感知、调试支持等,非常适合各种开发者使用。二、系统要求操作系统:Windows、macOS、Linux处理器:至少1GHz内存:至少512MBRAM硬盘空间:至少20
HTML5新特性深度解析
longdong7889
前端学习 html5 前端 html
HTML5新特性深度解析HTML5作为现代Web开发的基石,其LivingStandard模式持续为开发者带来创新工具。本文将深入剖析2023年值得关注的最新特性,通过技术解析与实战示例展现其应用场景。一、革新性API赋能Web应用1.1PopoverAPI:原生交互革命显示详情悬浮内容支持自动关闭和层级管理浏览器原生实现弹窗系统支持auto/manual状态控制无需JavaScript实现显隐逻
TypeScript 和 JavaScript 的区别
前端与小赵
理念 javascript typescript 前端
1.类型系统JavaScript:动态类型:变量可以在运行时改变其类型。没有内置的类型检查机制,在编译时不会进行类型检查。类型错误通常在运行时才会被发现。TypeScript:静态类型:变量在声明时需要指定类型,并且在编译时会进行类型检查。提供了丰富的类型系统,包括基本类型、接口、类、泛型等。类型错误可以在编译时被捕获,提高了代码的可靠性和可维护性。2.语法和特性JavaScript:基本语法包括
React生态、Vue生态与跨框架前端解决方案
Coder LM Wang
JavaScript 前端 react.js vue.js
React生态系统1基础框架React.js是一个用于构建UI的JavaScript库。2应用框架Next.js是基于React.js的完整应用框架。主要负责应用如何工作:应用架构:路由系统、页面结构渲染策略:服务端渲染(SSR)、静态生成(SSG)、客户端渲染性能优化:代码分割、图片优化、字体优化开发体验:热模块替换、TypeScript支持部署:Vercel平台集成、自托管选项3UI组件库MU
vue3+vite项目打包后css样式丢失
Angus-zoe
javascript 开发语言 ecmascript
问题:原因:默认情况下启用了CSS代码分割,CSS样式会被提取到单独的CSS文件中,会导致一些样式丢失的情况。通过将cssCodeSplit设置为false,可以禁用CSS代码分割,这样CSS样式将会内联到JavaScript中,而不是被提取到单独的CSS文件中。这种方式可以解决一些样式丢失的问题,因为样式将直接包含在构建后的JavaScript文件中,而不会受到代码分割的影响。解决方法:在vit
深度剖析 JavaScript 变量提升与暂时性死区:原理、实战与避坑指南
在JavaScript中,变量提升与暂时性死区影响着着程序的运行逻辑、性能表现以及可维护性。接下来将从底层原理、实际场景案例以及最佳实践全方位展开深度剖析。变量提升:JavaScript引擎背后的“隐形重构”JavaScript在执行代码前,引擎会率先开启编译流程,其中变量提升堪称关键一环。使用var关键字声明的变量以及函数声明,都会被自动“提升”至所在作用域的顶部。这一过程并非物理层面挪动代码,
Three.js 入门(补间动画Tween.js)
庸俗今天不摸鱼
three.Js学习 javascript 开发语言 ecmascript
本篇主要学习内容:Tween.Js补间动画点赞+关注+收藏=学会了1.什么是Tween.Js?TweenJS是一个由JavaScript语言编写的补间动画库,如果需要tweenjs辅助你生成动画,对于任何前端web项目,你都可以选择tweenjs库。如果你使用three.js开发web3d项目,使用tween.js辅助three.js生成动画效果也是比较好的选择。1.1)引入tween.Jsimp
大白话Webpack 配置与使用的详细步骤和插件应用
IT木昜
大白话前端高频面试题 webpack 前端 node.js
大白话Webpack配置与使用的详细步骤和插件应用啥是WebpackWebpack就像是一个超级管家,在我们开发网页的时候,会有各种各样的文件,像JavaScript文件、CSS文件、图片等等。这些文件就像是家里的各种物品,分散在不同的地方,而且有的物品还得按照特定顺序摆放、处理之后才能正常使用。Webpack这个管家就负责把这些分散的文件收集起来,按照我们的要求进行打包、处理,最后变成一个或几个
yarn如何用node替换
Yarn是一个流行的JavaScript包管理工具,它为npm提供了更快、更可靠的体验。尽管Yarn有其优势,但在许多情况下,我们可能想使用Node.js的本地包管理机制来替代Yarn。一、基本概念在开始之前,我们要明确一些基本个念:Node.js:一个高效的JavaScript运行环境,为构建服务器端应用程序提供支持。Yarn:一个Facebook开发的JavaScript包管理工具,用于处理项
【Javascript网页设计】产品展示 JavaScript 设计案例
Netsuite + 影刀
Javascript案例 javascript 前端 html
代码如下:产品展示页面body{font-family:Arial,sans-serif;margin:20px;text-align:center;}.product-container{display:flex;flex-wrap:wrap;justify-content:center;gap:20px;}.product-card{border:1pxsolid#ddd;padding:15
网络空间安全(13)上传验证绕过
IT 青年
网安知识库 网络空间安全
前言上传验证绕过是一种网络安全攻击手段,攻击者利用目标系统或应用程序在文件上传过程中存在的漏洞,绕过文件上传的验证机制,上传恶意文件,从而实现对目标系统的攻击。一、常见类型客户端验证绕过定义:客户端验证通常通过JavaScript在浏览器中执行,用于检查文件类型、大小等。客户端验证绕过是指攻击者通过禁用JavaScript或修改前端代码,绕过这些验证。绕过方法:禁用JavaScript:直接在浏览
react精简面试题
懒人村杂货铺
react.js 前端 前端框架
一、React基础1.React的核心特性是什么?答案:组件化开发:将UI拆分为独立可复用的组件。虚拟DOM(VirtualDOM):通过内存中的轻量级DOM结构优化真实DOM操作。单向数据流:数据通过props从父组件传递到子组件,状态变化可预测。JSX:允许在JavaScript中编写类似HTML的语法,增强代码可读性。2.类组件和函数组件的区别?答案:类组件:使用class定义,继承Reac
React Native v0.78 更新
Mr.NickJJ
React Native 系列 react native react.js javascript
这个版本在ReactNative中引入了React19,并带来了一些重要的新功能,例如Android矢量图(VectorDrawables)的原生支持以及iOS更好的Brownfield集成。亮点React19集成更小更快的发布节奏可选择在Metro中启用JavaScript日志新增对AndroidXMLDrawables的支持iOS上的ReactNativeFactory这个版本为开发者带来了更
深入理解 React.js:构建现代 Web 应用的核心技术
布兰妮甜
JavaScript - 行为 # React 前端 javascript react.js 前端框架
Hi,我是布兰妮甜!React.js是由Facebook开发并开源的一个用于构建用户界面的JavaScript库。自2013年发布以来,React迅速成为前端开发领域的主流工具之一。其组件化、声明式编程模型以及高效的虚拟DOM技术,使得开发者能够轻松构建高性能、可维护的Web应用。本文将深入探讨React.js的核心概念、优势以及如何在实际项目中应用。文章目录一、React.js的核心概念二、Re
http链接转成https的链接的几种方法
爱分享的程序员
前端 http https 网络协议
以下是一个将HTTP链接转换为HTTPS的JavaScript函数,处理了多种常见输入情况:functionconvertToHttps(url){if(typeofurl!=='string')returnurl;//移除首尾空格并处理空字符串consttrimmedUrl=url.trim();if(!trimmedUrl)return'https://';//替换HTTP协议(不区分大小写)
从入门到精通 JavaScript 1000例实战开发专栏--第1章:JavaScript 概述与环境搭建
小蘑菇二号
入门到精通 JavaScript 1000例实战开发 javascript 开发语言
目录第一章:JavaScript概述与环境搭建章节简介1.什么是JavaScript?2.开发工具的选择与安装3.第一个JavaScript程序学习收获第一章:JavaScript概述与环境搭建章节简介本章将带领读者了解JavaScript的基础概念,熟悉开发环境的搭建,并完成第一个简单的JavaScript程序。通过本章的学习,您将掌握JavaScript的基本用途、开发工具的选择以及如何快速上
使用Ajax完成与后台服务器的数据交互
星星不打輰
ajax 服务器 交互 edge浏览器
使用Ajax实现与后台服务器的数据交互Ajax(异步的JavaScript和XML)##注意Ajax为异步的异步:即为不同步,同步相当于是我们在向后台发送请求的时候,必须返回一个响应数据才可以在浏览器下一步操作(形象描述:一次聊天,两者进行一问一答)–》这就叫做同步异步就是一者向另外一者发送信息,但是不等对方回复,可以继续向其发送信息**Ajax与服务器之间进行交换数据,更新的是部分网页的信息,而
Vue 组件中数据的定义
weixin_45408068
Vue 组件中数据的定义
Vue组件中数据的定义为什么组件中的data选项是一个函数,而根实例中是对象原因:(1).组件是一个独立的整体,那么数据也应该是一个独立的【80%】(2).多人开发,数据如果不是独立的,那么数据会冲突【5%】(3).javascript最大的特点:函数式编程,而函数本身就有一个独立作用域【15%】为什么组件中的data函数要有返回值,并且返回值是一个对象,不能是其他的吗?原因:因为data选项要经
Vue 过滤器
JSON_L
前端 # Vue 前端 vue.js
Vue渐进式JavaScript框架基于Vue2的学习笔记-Vue使用-过滤器目录过滤器优化图片路径处理定义过滤器使用多个过滤器总结过滤器优化图片路径处理文件路径经过管道过滤器处理后,返回给图片路径,示例如下:ajax-axios{{item.title}}定义过滤器在vue中定义过滤器。示例如下:Vue.filter("imgFilter",(url)=>{returnurl.replace("
JavaScript 数组常用方法详细教程
我是如此相信ᯤ⁶⁶ᴳ
javascript 开发语言 数组
在JavaScript中,数组是一种非常重要的数据结构,用于存储多个值。JS提供了许多内置方法来操作数组,使得数据处理变得更加简单和高效。本文将详细介绍一些常用的JavaScript数组方法,这些不但是平时开发常用的方法,也是面试的重点,现在带着大家一起复习复习~1.push()和pop()push()push()方法用于在数组末尾添加一个或多个元素,并返回新数组的长度。letarr=[1,2,3
使用HTML,CSS和JavaScript创建Chrome扩展程序
海拥✘
Google 100个前端优质项目 javascript css chrome
介绍谷歌浏览器是开发人员和普通用户最喜欢的浏览器之一。我在所有设备上都使用了GoogleChrome浏览器,它可以帮助我同步书签,浏览器历史记录,密码管理器等等。对于台式机,除了可以在Internet上浏览以外,您还可以做很多事情。您可以测试您的网页和全部。通过使用扩展程序,谷歌浏览器变得更加强大。因此,今天,我们将研究如何使用HTML,CSS和JavaScript创建您的第一个GoogleChr
关于旗正规则引擎中的MD5加密问题
何必如此
jsp MD5 规则 加密
一般情况下,为了防止个人隐私的泄露,我们都会对用户登录密码进行加密,使数据库相应字段保存的是加密后的字符串,而非原始密码。
在旗正规则引擎中,通过外部调用,可以实现MD5的加密,具体步骤如下:
1.在对象库中选择外部调用,选择“com.flagleader.util.MD5”,在子选项中选择“com.flagleader.util.MD5.getMD5ofStr({arg1})”;
2.在规
【Spark101】Scala Promise/Future在Spark中的应用
bit1129
Promise
Promise和Future是Scala用于异步调用并实现结果汇集的并发原语,Scala的Future同JUC里面的Future接口含义相同,Promise理解起来就有些绕。等有时间了再仔细的研究下Promise和Future的语义以及应用场景,具体参见Scala在线文档:http://docs.scala-lang.org/sips/completed/futures-promises.html
spark sql 访问hive数据的配置详解
daizj
spark sql hive thriftserver
spark sql 能够通过thriftserver 访问hive数据,默认spark编译的版本是不支持访问hive,因为hive依赖比较多,因此打的包中不包含hive和thriftserver,因此需要自己下载源码进行编译,将hive,thriftserver打包进去才能够访问,详细配置步骤如下:
1、下载源码
2、下载Maven,并配置
此配置简单,就略过
HTTP 协议通信
周凡杨
java httpclient http 通信
一:简介
HTTPCLIENT,通过JAVA基于HTTP协议进行点与点间的通信!
二: 代码举例
测试类:
import java
java unix时间戳转换
g21121
java
把java时间戳转换成unix时间戳:
Timestamp appointTime=Timestamp.valueOf(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()))
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:m
web报表工具FineReport常用函数的用法总结(报表函数)
老A不折腾
web报表 finereport 总结
说明:本次总结中,凡是以tableName或viewName作为参数因子的。函数在调用的时候均按照先从私有数据源中查找,然后再从公有数据源中查找的顺序。
CLASS
CLASS(object):返回object对象的所属的类。
CNMONEY
CNMONEY(number,unit)返回人民币大写。
number:需要转换的数值型的数。
unit:单位,
java jni调用c++ 代码 报错
墙头上一根草
java C++ jni
#
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00000000777c3290, pid=5632, tid=6656
#
# JRE version: Java(TM) SE Ru
Spring中事件处理de小技巧
aijuans
spring Spring 教程 Spring 实例 Spring 入门 Spring3
Spring 中提供一些Aware相关de接口,BeanFactoryAware、 ApplicationContextAware、ResourceLoaderAware、ServletContextAware等等,其中最常用到de匙ApplicationContextAware.实现ApplicationContextAwaredeBean,在Bean被初始后,将会被注入 Applicati
linux shell ls脚本样例
annan211
linux linux ls源码 linux 源码
#! /bin/sh -
#查找输入文件的路径
#在查找路径下寻找一个或多个原始文件或文件模式
# 查找路径由特定的环境变量所定义
#标准输出所产生的结果 通常是查找路径下找到的每个文件的第一个实体的完整路径
# 或是filename :not found 的标准错误输出。
#如果文件没有找到 则退出码为0
#否则 即为找不到的文件个数
#语法 pathfind [--
List,Set,Map遍历方式 (收集的资源,值得看一下)
百合不是茶
list set Map遍历方式
List特点:元素有放入顺序,元素可重复
Map特点:元素按键值对存储,无放入顺序
Set特点:元素无放入顺序,元素不可重复(注意:元素虽然无放入顺序,但是元素在set中的位置是有该元素的HashCode决定的,其位置其实是固定的)
List接口有三个实现类:LinkedList,ArrayList,Vector
LinkedList:底层基于链表实现,链表内存是散乱的,每一个元素存储本身
解决SimpleDateFormat的线程不安全问题的方法
bijian1013
java thread 线程安全
在Java项目中,我们通常会自己写一个DateUtil类,处理日期和字符串的转换,如下所示:
public class DateUtil01 {
private SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public void format(Date d
http请求测试实例(采用fastjson解析)
bijian1013
http 测试
在实际开发中,我们经常会去做http请求的开发,下面则是如何请求的单元测试小实例,仅供参考。
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.httpclient.HttpClient;
import
【RPC框架Hessian三】Hessian 异常处理
bit1129
hessian
RPC异常处理概述
RPC异常处理指是,当客户端调用远端的服务,如果服务执行过程中发生异常,这个异常能否序列到客户端?
如果服务在执行过程中可能发生异常,那么在服务接口的声明中,就该声明该接口可能抛出的异常。
在Hessian中,服务器端发生异常,可以将异常信息从服务器端序列化到客户端,因为Exception本身是实现了Serializable的
【日志分析】日志分析工具
bit1129
日志分析
1. 网站日志实时分析工具 GoAccess
http://www.vpsee.com/2014/02/a-real-time-web-log-analyzer-goaccess/
2. 通过日志监控并收集 Java 应用程序性能数据(Perf4J)
http://www.ibm.com/developerworks/cn/java/j-lo-logforperf/
3.log.io
和
nginx优化加强战斗力及遇到的坑解决
ronin47
nginx 优化
先说遇到个坑,第一个是负载问题,这个问题与架构有关,由于我设计架构多了两层,结果导致会话负载只转向一个。解决这样的问题思路有两个:一是改变负载策略,二是更改架构设计。
由于采用动静分离部署,而nginx又设计了静态,结果客户端去读nginx静态,访问量上来,页面加载很慢。解决:二者留其一。最好是保留apache服务器。
来以下优化:
java-50-输入两棵二叉树A和B,判断树B是不是A的子结构
bylijinnan
java
思路来自:
http://zhedahht.blog.163.com/blog/static/25411174201011445550396/
import ljn.help.*;
public class HasSubtree {
/**Q50.
* 输入两棵二叉树A和B,判断树B是不是A的子结构。
例如,下图中的两棵树A和B,由于A中有一部分子树的结构和B是一
mongoDB 备份与恢复
开窍的石头
mongDB备份与恢复
Mongodb导出与导入
1: 导入/导出可以操作的是本地的mongodb服务器,也可以是远程的.
所以,都有如下通用选项:
-h host 主机
--port port 端口
-u username 用户名
-p passwd 密码
2: mongoexport 导出json格式的文件
[网络与通讯]椭圆轨道计算的一些问题
comsci
网络
如果按照中国古代农历的历法,现在应该是某个季节的开始,但是由于农历历法是3000年前的天文观测数据,如果按照现在的天文学记录来进行修正的话,这个季节已经过去一段时间了。。。。。
也就是说,还要再等3000年。才有机会了,太阳系的行星的椭圆轨道受到外来天体的干扰,轨道次序发生了变
软件专利如何申请
cuiyadll
软件专利 申请
软件技术可以申请软件著作权以保护软件源代码,也可以申请发明专利以保护软件流程中的步骤执行方式。专利保护的是软件解决问题的思想,而软件著作权保护的是软件代码(即软件思想的表达形式)。例如,离线传送文件,那发明专利保护是如何实现离线传送文件。基于相同的软件思想,但实现离线传送的程序代码有千千万万种,每种代码都可以享有各自的软件著作权。申请一个软件发明专利的代理费大概需要5000-8000申请发明专利可
Android学习笔记
darrenzhu
android
1.启动一个AVD
2.命令行运行adb shell可连接到AVD,这也就是命令行客户端
3.如何启动一个程序
am start -n package name/.activityName
am start -n com.example.helloworld/.MainActivity
启动Android设置工具的命令如下所示:
# am start -
apache虚拟机配置,本地多域名访问本地网站
dcj3sjt126com
apache
现在假定你有两个目录,一个存在于 /htdocs/a,另一个存在于 /htdocs/b 。
现在你想要在本地测试的时候访问 www.freeman.com 对应的目录是 /xampp/htdocs/freeman ,访问 www.duchengjiu.com 对应的目录是 /htdocs/duchengjiu。
1、首先修改C盘WINDOWS\system32\drivers\etc目录下的
yii2 restful web服务[速率限制]
dcj3sjt126com
PHP yii2
速率限制
为防止滥用,你应该考虑增加速率限制到您的API。 例如,您可以限制每个用户的API的使用是在10分钟内最多100次的API调用。 如果一个用户同一个时间段内太多的请求被接收, 将返回响应状态代码 429 (这意味着过多的请求)。
要启用速率限制, [[yii\web\User::identityClass|user identity class]] 应该实现 [[yii\filter
Hadoop2.5.2安装——单机模式
eksliang
hadoop hadoop单机部署
转载请出自出处:http://eksliang.iteye.com/blog/2185414 一、概述
Hadoop有三种模式 单机模式、伪分布模式和完全分布模式,这里先简单介绍单机模式 ,默认情况下,Hadoop被配置成一个非分布式模式,独立运行JAVA进程,适合开始做调试工作。
二、下载地址
Hadoop 网址http:
LoadMoreListView+SwipeRefreshLayout(分页下拉)基本结构
gundumw100
android
一切为了快速迭代
import java.util.ArrayList;
import org.json.JSONObject;
import android.animation.ObjectAnimator;
import android.os.Bundle;
import android.support.v4.widget.SwipeRefreshLayo
三道简单的前端HTML/CSS题目
ini
html Web 前端 css 题目
使用CSS为多个网页进行相同风格的布局和外观设置时,为了方便对这些网页进行修改,最好使用( )。http://hovertree.com/shortanswer/bjae/7bd72acca3206862.htm
在HTML中加入<table style=”color:red; font-size:10pt”>,此为( )。http://hovertree.com/s
overrided方法编译错误
kane_xie
override
问题描述:
在实现类中的某一或某几个Override方法发生编译错误如下:
Name clash: The method put(String) of type XXXServiceImpl has the same erasure as put(String) of type XXXService but does not override it
当去掉@Over
Java中使用代理IP获取网址内容(防IP被封,做数据爬虫)
mcj8089
免费代理IP 代理IP 数据爬虫 JAVA设置代理IP 爬虫封IP
推荐两个代理IP网站:
1. 全网代理IP:http://proxy.goubanjia.com/
2. 敲代码免费IP:http://ip.qiaodm.com/
Java语言有两种方式使用代理IP访问网址并获取内容,
方式一,设置System系统属性
// 设置代理IP
System.getProper
Nodejs Express 报错之 listen EADDRINUSE
qiaolevip
每天进步一点点 学习永无止境 nodejs 纵观千象
当你启动 nodejs服务报错:
>node app
Express server listening on port 80
events.js:85
throw er; // Unhandled 'error' event
^
Error: listen EADDRINUSE
at exports._errnoException (
C++中三种new的用法
_荆棘鸟_
C++ new
转载自:http://news.ccidnet.com/art/32855/20100713/2114025_1.html
作者: mt
其一是new operator,也叫new表达式;其二是operator new,也叫new操作符。这两个英文名称起的也太绝了,很容易搞混,那就记中文名称吧。new表达式比较常见,也最常用,例如:
string* ps = new string("
Ruby深入研究笔记1
wudixiaotie
Ruby
module是可以定义private方法的
module MTest
def aaa
puts "aaa"
private_method
end
private
def private_method
puts "this is private_method"
end
end