1、垃圾回收机制
内存中的生命周期
1、内存分配
2、内存使用(读写)
3、内存回收,使用完毕之后,垃圾回收器完成
内存泄漏:该回收的,由于某些未知因素,未释放,叫做内存泄漏
栈:数据存在其中会自动释放
堆:对象,根据程序员的操作来决定释放
一、引用计数法
1、记录引用次数
2、计数 ++ 或者 --
3、引用次数为0时,释放内存
原理:跟踪记录每个值被引用的次数。
当垃圾收集器下一次运行时,它就会释放引用次数是0的值所占的内存。
如果一个对象已经没有指向他的引用了,那么就认为不在需要,
循环引用的内存,无法被释放
let obj1={uname:"lisi"}let a=obj1//存的是内存地址,引用计数为2a=null//--,引用计数为1//缺点:占内存消耗; 循环引用问题,内存无法被释放
看看这个
两个对象被创建,并互相引用,形成了一个循环。
无法计数无法为0,他们的计数均为1,无法释放,
计数算法考虑到它们互相都有至少一次引用,所以它们不会被回收。
let obj2={a:obj3}
let obj3={b:obj2}
obj2 = null
二、标记清除
垃圾回收器将定期从根开始,找所有从根开始引用的对象,然后找这些对象引用的对象……从根开始,垃圾回收器将找到所有可以获得的对象和收集所有不能获得的对象。
循环引用不再是问题了
在上面的示例中,函数调用返回之后,两个对象从全局对象出发无法获取。因此,他们将会被垃圾回收器回收。
2、闭包
在 JavaScript 中,闭包会随着函数的创建而被同时创建。
内层函数+外层函数的变量 与函数,内层函数使用了外层函数的变量
function outer() {let i = 10function inner() {console.log(i)}return inner//外部函数调用内部函数实现功能}let a = outer()a()a() //输出两次10
外部可以访问函数内部的变量
闭包会在父函数外部,改变父函数内部变量的值。
下面这个函数,他不是改变了全局变量,而是函数可以访问全局变量并且利用表达式与打印,进行函数内部的输出表达,当出了这块函数,全局变量num还是0.
JavasSript 语言的特别之处就在于:函数内部可以直接读取全局变量,但是在函数外部无法读取函数内部的局部变量。
let num = 0function test1() {num++console.log(`这是函数调用的第${num}次`)}test1()test1()num = 300test1()
闭包函数
一个函数的返回值是一个内部函数,并且这个内部函数调用了父级函数的变量。
<script>function outer() {let num = 0function inner() {num++console.log(`这是函数调用的第${num}次`)}return inner}let a = outer()a()a()a()num = 21a()</script>
3、Math对象
是一个内置对象,它拥有一些数学常数属性和数学函数方法。
来看看常用的数学成员,更多的成员可以上网查。
成员 | 作用 |
E | 欧拉常数,也是自然对数的底数,约等于 2.718 。 |
PI | 获取圆周率,结果为3.141592653589793。 |
abs(x) | 返回一个数的绝对值。 |
sqrt(x) | 获取x的平方根 |
cbrt(x) | 返回一个数的立方根。 |
max(x) | 返回零到多个数值中最大值。 |
min(x) | 返回零到多个数值中最小值。 |
pow(x,y) | 返回一个数的 y 次幂。 |
ceil(x) | 向上取整。 |
floor(x) | 向下取整。 |
round(x) | 返回四舍五入后的整数。 |
random | 返回一个 0 到 1 之间的伪随机数。随机数[0,1) |
log(x) | 返回一个数的自然对数(㏒e,即 ㏑)。 |
log2(x)/log(x) | 返回一个数以 2或者10 为底数的对数。 |
sign(x) | 返回一个数的符号,得知一个数是正数、负数还是 0 |
获取n~m的随机数
console.log(Math.floor(Math.random()*((n-m)+1))+m)
4、Date对象
创建Date对象,将返回一个字符串,以下是四种创建方法
let d1 = new Date(); //获取当前时间
let d2= new Date(milliseconds); // 参数为毫秒
let d3 = new Date(dateString);
let d4 = new Date(year, month, day, hours, minutes, seconds, milliseconds);
milliseconds 参数是一个 Unix 时间戳,它是一个整数值,表示自 1970 年 1 月 1 日 00:00:00 UTC(the Unix epoch)以来的毫秒数。
dateString 参数表示日期的字符串值。
year, month, day, hours, minutes, seconds, milliseconds 分别表示年、月、日、时、分、秒、毫秒。
<script>let today=new Date()console.log('today='+today)let d1 = new Date("October 13, 1975 11:13:00")console.log('d1='+d1)let d2=new Date("2022-2-17 23:03:46")console.log('d2='+d2)let d3=new Date(100000000000)console.log('d3='+d3)let d4=new Date(2018,8,19,6,26,21)console.log('d4='+d4)</script>
方法 | 描述 |
---|---|
getDate() | 从 Date 对象返回一个月中的某一天 (1 ~ 31)。 |
getDay() | 从 Date 对象返回一周中的某一天 (0 ~ 6)。 |
getFullYear() | 从 Date 对象以四位数字返回年份。 |
getHours() | 返回 Date 对象的小时 (0 ~ 23)。 |
getMinutes() | 返回 Date 对象的分钟 (0 ~ 59)。 |
getMouth() | 从 Date 对象返回月份 (0 ~ 11)。 |
getSeconds() | 返回 Date 对象的秒数 (0 ~ 59)。 |
getMilliseconds() | 返回 Date 对象的毫秒数 (0 ~ 59)。 |
getTime() | 返回 1970 年 1 月 1 日至今的毫秒数(0~999。 |
parse() | 返回1970年1月1日午夜到指定日期(字符串)的毫秒数。 |
setDate() | 设置 Date 对象中月的某一天 (1 ~ 31)。 |
setFullYear() | 设置 Date 对象中的年份(四位数字)。 |
setHours() | 设置 Date 对象中的小时 (0 ~ 23)。 |
setMinutes() | 设置 Date 对象中的分钟 (0 ~ 59)。 |
setMouth() | 设置 Date 对象中月份 (0 ~ 11)。 |
setSeconds() | 设置 Date 对象中的秒钟 (0 ~ 59)。 |
setTime() | setTime() 方法以毫秒设置 Date 对象。 |
setYear() | 已废弃。请使用 setFullYear() 方法代替。 |
toDateString() | 把 Date 对象的日期部分转换为字符串。 |
toString() | 把 Date 对象转换为字符串。 |
toTimeString() | 把 Date 对象的时间部分转换为字符串。 |
UTC() | 根据世界时返回 1970 年 1 月 1 日 到指定日期的毫秒数。 |
举个例子
<script>let date=new Date()console.log(date+'')let y=date.getFullYear()console.log(y+'年')let m=date.getMonth()console.log(m+'月')let day = date.getDate()console.log(day+'号')// 时分秒let hh = date.getHours()let mm = date.getMinutes()let ss = date.getSeconds()console.log(hh+'时')console.log(mm+'分')console.log(ss+'秒')let w = date.getDay()console.log('星期'+w)console.log(date.toString()+' toString()')console.log(date.toTimeString()+' toTimeString()')console.log(date.toDateString()+' toDateString()')</script>
5、展开运算符
关于数组内全部元素的输出,除了遍历,还有没有不遍历的方法??
假如有一个数组,你要如何将其中的元素不遍历也可以输出?
let a=[3,2,11]
我想大家一般直接这样:
let c=a[0]
let c1=a[1]
let c2=a[2]
那么问题来了,要是,数组里的元素有上万个呢,虽然有点夸张,但是,它不能被忽视对吧
哈哈,不装了,介绍一下一个运算符,它是三个英文的句号
展开运算符:...
不仅是数组,还有字符串也可用
<script>let a=[3,2,11]//...展开运算符,可以把数组与对象展开document.write(...a+'<br>')//将列表拆开document.write(Math.max(...a))//不可以接数组与对象,可以是一串数字</script>
6、获取元素对象
在 HTML DOM 中, 元素对象代表着一个 HTML 元素。
方法 | |
document.getElementById() | |
document.getElementsByClassName() | 返回文档中所有指定类名的元素集合 |
document.getElementsByName() | |
document.getElementsByTagName() | 返回指定标签名的所有子元素集合。 |
Document.querySelector("选择器") | 拿到满足第一个。 |
querySelectorAll(" ") | 拿到伪数组。 |
<body><p>段落111</p><p>段落222</p><p>段落333</p><p>段落444</p><div>你是一个盒子111</div><div>你是一个盒子222</div><div>你是一个盒子333</div><ul><li>11111111小li</li><li name="k2">2222222小li</li><li class="f3">333333小li</li><li id="d4">4444444小li</li></ul><script>let k2=document.getElementsByName("k2")console.log(k2)let f3=document.getElementsByClassName("f3")console.log(f3)let d4=document.getElementById("d4")console.log(d4)let d=document.getElementsByTagName("div")let p1=document.querySelector("p")console.log(p1)let p2=document.querySelectorAll("p")console.log(p2)for (let i in p2) {console.log(p2[i])}</script>
</body>