一,JavaScript简单了解
1.什么是JavaScript
JavaScript简称JS,是较为流行的一种前端编程语言,是一种脚本语言,通过解释器运行,主要在客户端(浏览器)上运行,现在也可以基于node.js在服务器端运行
2.JavaScript的应用场景
网页开发(更复杂的特效和用户交互)
网页游戏开发
服务器开发(node.js)
桌面程序开发(Electron, VSCode 就是这么来的)
手机 app 开发
3.JavaScript与HTML、CSS的关系
HTML: 网页的结构(骨)
CSS: 网页的表现(皮)
JavaScript: 网页的行为(魂)
4.JavaScript的运行过程
编写的代码是保存在文件中的, 也就是存储在硬盘(外存上).
双击 .html 文件浏览器(应用程序)就会读取文件, 把文件内容加载到内存中(数据流向: 硬盘 => 内存)
浏览器会解析用户编写的代码, 把代码翻译成二进制的, 能让计算机识别的指令(解释器的工作)
得到的二进制指令会被 CPU 加载并执行(数据流向: 内存 => CPU)
二,JavaScript的相关语法
JavaScript作为一种较为流行的编程语言,有其自己的语法规则,但是在计算机编程语言的圈子中,各种编程语言的语法规则有很多的类似之处,由于之前已经详细讲解Java和C的语法规则,所以这里只针对JS中不同的语法进行讲解
2.JavaScript的书写形式
1.行内式
行内式直接嵌入到html元素内部
JS中字符串常量可以使用单引号表示,也可以使用双引号表示;HTML中推荐使用双引号,JS中推荐使用单引号!
2.内嵌式
内嵌式写在script标签中
3.外部式
外部式适合代码较多的情况,此时需要将代码单独写入一个js文件中
4.js结束符
分号或者回车,注意:格式统一,分号就全部用分号。
三、垃圾回收机制
1、垃圾回收的必要性
由于字符串、对象和数组没有固定大小,所有当他们的大小已知时,才能对他们进行动态的存储分配。JavaScript程序每次创建字符串、数组或对象时,解释器都必须分配内存来存储那个实体。只要像这样动态地分配了内存,最终都要释放这些内存以便他们能够被再用,否则,JavaScript的解释器将会消耗完系统中所有可用的内存,造成系统崩溃。
这段话解释了为什么需要系统需要垃圾回收,JS不像C/C++,他有自己的一套垃圾回收机制(Garbage Collection)。JavaScript的解释器可以检测到何时程序不再使用一个对象了,当他确定了一个对象是无用的时候,他就知道不再需要这个对象,可以把它所占用的内存释放掉了。例如:
var a = "before";
var b = "override a";
var a = b; //重写a
这段代码运行之后,“before”这个字符串失去了引用(之前是被a引用),系统检测到这个事实之后,就会释放该字符串的存储空间以便这些空间可以被再利用。
2、垃圾回收原理浅析
现在各大浏览器通常用采用的垃圾回收有两种方法:标记清除、引用计数。
2.1、标记清除
这是javascript中最常用的垃圾回收方式。当变量进入执行环境是,就标记这个变量为“进入环境”。从逻辑上讲,永远不能释放进入环境的变量所占用的内存,因为只要执行流进入相应的环境,就可能会用到他们。当变量离开环境时,则将其标记为“离开环境”。
垃圾收集器在运行的时候会给存储在内存中的所有变量都加上标记。然后,它会去掉环境中的变量以及被环境中的变量引用的标记。而在此之后再被加上标记的变量将被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了。最后。垃圾收集器完成内存清除工作,销毁那些带标记的值,并回收他们所占用的内存空间。
关于这一块,建议读读Tom大叔的几篇文章,关于作用域链的一些知识详解,读完差不多就知道了,哪些变量会被做标记。
3、减少JavaScript中的垃圾回收
首先,最明显的,new关键字就意味着一次内存分配,例如 new Foo()。最好的处理方法是:在初始化的时候新建对象,然后在后续过程中尽量多的重用这些创建好的对象。
另外还有以下三种内存分配表达式(可能不像new关键字那么明显了):
{} (创建一个新对象)
[] (创建一个新数组)
function() {…} (创建一个新的方法,注意:新建方法也会导致垃圾收集!!)
四、闭包
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 内层函数+外层函数的变量 。内层函数使用了外层函数的变量
// function outer() {
// let i = 10
// function inner() {
// console.log(i)
// }
// return inner
// }
// let a = outer()
// a()
// a()
// 闭包:外部访问函数内部的变量
// let num = 0
// function test1() {
// num++
// console.log(`这是函数调用的第${num}次`)
// }
// test1()
// test1()
// num = 300
// test1()
function outer() {
let num = 0
function inner() {
num++
console.log(`这是函数调用的第${num}次`)
}
return inner
}
let a = outer()
a()
a()
a()
num = 21
a()
</script>
</body>
</html>
八、js节点查找节点的查找方法
A.parentNode 查找A节点的父节点
A.childNodes 查找A节点内的所有子节点 包含文本节点 元素节点 属性节点 注释节点
A.children 查找A节点内的所有子元素节点
A.firstChild 查找第一个子节点
A.firstElementChild 查找第一个子元素节点
A.lastChild
A.lastElementChild
A.nextSibling 查找下一个兄弟节点
A.nextElementSibling 查找下一个兄弟元素节点
A.previousSibling 查找上一个兄弟节点
A.previousElementSibling 查找上一个兄弟元素节点`
时间倒计时作业
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>
距离2025年1月1日还有:<br>
<span id="d">0</span>天
<span id="h">0</span>小时
<span id="m">0</span>分钟
<span id="s">0</span>秒
</div>
<script>
let New_Date = new Date('2025-01-01T00:00:00');
function updateCountdown(){
let Now_Date = new Date();
let F = New_Date - Now_Date;
let days = Math.floor(F / (1000 * 60 * 60 * 24));
let hours = Math.floor((F % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
let minutes = Math.floor((F % (1000 * 60 * 60)) / (1000 * 60));
let seconds = Math.floor((F % (1000 * 60)) / 1000);
document.getElementById('d').textContent = days;
document.getElementById('h').textContent = hours;
document.getElementById('m').textContent = minutes;
document.getElementById('s').textContent = seconds;
}
updateCountdown();
setInterval(updateCountdown, 1000);
</script>
</body>
</html>