js基础知识+练习

一,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中不同的语法进行讲解


1.第一个JS程序

<!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><!-- 内联 --><button onclick="console.log('5556666777');">点击</button><!-- <script>let btn = document.querySelector("button")btn.addEventListener("click", function () {alert("点击了按钮")})</script> --><script src="./10-index.js"></script>
</body></html>
alert("555")

2.JavaScript的书写形式


1.行内式
行内式直接嵌入到html元素内部


JS中字符串常量可以使用单引号表示,也可以使用双引号表示;HTML中推荐使用双引号,JS中推荐使用单引号!

2.内嵌式
内嵌式写在script标签中


3.外部式

外部式适合代码较多的情况,此时需要将代码单独写入一个js文件中

3.js的注释

// 单行注释    ctrl+//*这是js中的多行注释*/

4.js结束符

分号或者回车,注意:格式统一,分号就全部用分号。

 5.输入输出语法

<!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>// 输入// prompt("提示语")// 输出语法// 向body中输出内容,能够识别标签,解析成为网页元素document.write("<h1>要输出的内容</h1>")// 警示语法----弹出警告框alert("要输入的内容")// 控制台输出,程序员进行调试时使用的console.log("控制台打印")</script>
</body></html>

6.变量的使用

<!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>let passwdpasswd = "123456"console.log(passwd)// prompt("请输入您的密码:")//  变量的初始化let uname = "zhangsan"passwd = "lisi"console.log(passwd)// let uname = ""let age1 = 21, age2 = 22console.log(age1, age2)</script>
</body></html>


JS中的任何变量都定义成var或者let,变量的类型由编译器来识别


动态类型
理解动态类型需要从两方面入手:

JS 的变量类型是程序运行过程中才确定的(运行到 = 语句才会确定类型)

var a = 10; // 数字
var b = "hehe"; // 字符串
随着程序运行, 变量的类型可能会发生改变

var a = 10; // 数字
a = "hehe"; // 字符串

通过这个图片可以清楚地了解语言的强弱和动静态的大致分布

7.基本数据类型

number数字. 不区分整数和小数.
booleantrue 真, false 假.
string字符串类型.
undefined只有唯一的值 undefined. 表示未定义的值.
null只有唯一的值 null. 表示空值.

注意:

JS中不区分整型和浮点型数字,统一称为number类型

NAN表示当前的结果不是一个number类型

字符串与数字进行拼接会得到一个字符串(因为此时会将数字隐士转换成一个字符串)

可以使用isNAN函数判定是不是一个非数字

8.字符串类型

JS中字符串字面值需要使用引号引起来,单引号双引号均可!

字符串长度


求解字符串长度直接使用String的length属性即可
JS中字符串长度的单位为字符的数量!

字符串拼接


JS中字符串拼接同Java中一样都是用“+”来进行拼接,但是JS是一种弱类型语言,存在隐士类型转换,所以拼接的情况也更复杂

1.字符串与字符串拼接
2.字符串与数字拼接
当数字和字符串进行拼接的时候,编译器会自动将数字类型隐士转换成字符串类型来进行拼接!

9.undefined未定义数据类型


如果一个变量没有被初始化过,结果就是undefined,是undefined类型

var a;
console.log(a)


undefined和字符串进行相加,结果进行字符串拼接
undefined和数字相加,结果为NaN


10.null空值类型


null表示当前的变量是一个“空值”

null值与数字相加为数字本身
null值与字符串相加,结果进行字符串拼接
注意:null类型与undefined类型的异同

null和undefined都表示取值非法的情况,但是侧重点不同

null表示当前的值为空(相当于一个空的盒子)

undefined表示当前的变量未定义(相当于连盒子都没有)

11.数组

1.创建数组
1.使用new关键字创建
let arr = new Array(); Array的A要大写
2.使用字面常量方式创建
let arr = [1,2,'haha',false]; 数组中保存的内容被称为元素,JS这种不要求元素是相同类型
2.获取数组元素
使用下标的方式访问数组元素(从0开始)
如果下标超出范围读取元素,则结果为undefined

3.新增数组元素
通过修改length新增(相当于在末尾新增元素,新增的元素默认值为undefined)
通过下标新增(如果下标超出范围赋值元素,则会给指定位置插入新元素)


12.函数


1.语法格式
 

//创建函数/函数声明/函数定义
function 函数名(形参列表) {
函数体
return 返回值;
}// 函数调用
函数名(实参列表) // 不考虑返回值
返回值 = 函数名(实参列表) // 考虑返回值
函数定义并不会执行函数体内容,必须要调用才会执行,调用几次就会执行几次调用函数的时候进行函数内部执行,函数结束时回到调用位置继续执行函数的定义和调用的先后顺序没有要求(这点和变量不同,变量必须先定义再使用)

2.关于参数个数(实参和形参个数不匹配)
如果实参个数比形参个数多,则多出的参数不参与函数运算

如果实参个数比形参个数少,则此时多出来的形参值为undefined


3.函数表达式
函数表达式是另一种函数的定义方式

let add = function(){
}
形如function(){}这样的写法定义了一个匿名函数,然后将这个匿名函数用一个变量来表示称为函数表达式,后面就可以通过这个add变量来调用函数了

13.作用域和作用域链
作用域:

全局作用域:在整个script标签中,或者单独的js文件中生效

局部作用域/函数作用域:在函数内部生效

作用域链:

函数可以定义在函数内部(这点不同于java的语法)

内层函数可以访问外层函数的局部变量(内部函数可以访问外部函数的变量,采取的是链式查找的方式,从内到外依次进行查找)


14.对象


1.使用字面常量创建对象(常用)
var student = {
name: '蔡徐坤',
height: 175,
weight: 170,
sayHello: function() {
console.log("hello");
}
};
注意:

使用{ }创建对象

属性和方法使用键值对的形式来组织

键值对之间使用“,”分割,最后一个属性后面的“,”可有可无

键和值之间使用“:”分割

方法的值是一个匿名函数

2.使用new Object创建对象
var student = new Object(); // 和创建数组类似
student.name = "蔡徐坤";
student.height = 175;
student['weight'] = 170;
student.sayHello = function () {
console.log("hello");
}
3.使用对象的属性和方法
使用“.”成员访问运算符来访问属性

使用[ ]访问属性,此时需要加上引号

三、垃圾回收机制

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大叔的几篇文章,关于作用域链的一些知识详解,读完差不多就知道了,哪些变量会被做标记。

2.2、引用计数


另一种不太常见的垃圾回收策略是引用计数。引用计数的含义是跟踪记录每个值被引用的次数。当声明了一个变量并将一个引用类型赋值给该变量时,则这个值的引用次数就是1。相反,如果包含对这个值引用的变量又取得了另外一个值,则这个值的引用次数就减1。当这个引用次数变成0时,则说明没有办法再访问这个值了,因而就可以将其所占的内存空间给收回来。这样,垃圾收集器下次再运行时,它就会释放那些引用次数为0的值所占的内存。

<!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>//内存中的生命周期// 1、内存分配// 2、内存使用// 3、内存回收,使用完毕之后,垃圾回收器完成// 内存泄漏:该回收的,由于某些未知因素,未释放,叫做内存泄漏// 栈// 堆// js:引用计数法   标记清除法// 引用计数法  :如果一个对象已经没有指向他的引用了,那么就认为不在需要,// 内存消耗、循环引用的内存,无法被释放// 1、记录引用次数// 2、++   --// 3、引用次数为0时,释放内存// let arr = [1, 2, 3, 4]let obj1 = {uname: "zhanggsan"}let a = obj1a = null// 标记清除  从根部查找内存中的对象,凡是能找到的,都是我要进行使用的let obj2 = {a: obj3}let obj3 = {b: obj2}obj2 = null</script></body></html>

3、减少JavaScript中的垃圾回收


首先,最明显的,new关键字就意味着一次内存分配,例如 new Foo()。最好的处理方法是:在初始化的时候新建对象,然后在后续过程中尽量多的重用这些创建好的对象。

另外还有以下三种内存分配表达式(可能不像new关键字那么明显了):

{} (创建一个新对象)
[] (创建一个新数组)
function() {…} (创建一个新的方法,注意:新建方法也会导致垃圾收集!!)


3.1、对象object优化


为了最大限度的实现对象的重用,应该像避使用new语句一样避免使用{}来新建对象。

{“foo”:”bar”}这种方式新建的带属性的对象,常常作为方法的返回值来使用,可是这将会导致过多的内存创建,因此最好的解决办法是:每一次函数调用完成之后,将需要返回的数据放入一个全局的对象中,并返回此全局对象。如果使用这种方式,就意味着每一次方法调用都会导致全局对象内容的修改,这有可能会导致错误的发生。因此,一定要对此全局对象的使用进行详细的注释和说明。

有一种方式能够保证对象(确保对象prototype上没有属性)的重复利用,那就是遍历此对象的所有属性,并逐个删除,最终将对象清理为一个空对象。

cr.wipe(obj)方法就是为此功能而生,代码如下:// 删除obj对象的所有属性,高效的将obj转化为一个崭新的对象!
cr.wipe = function (obj) {for (var p in obj) {if (obj.hasOwnProperty(p))delete obj[p];}
}; 


有些时候,你可以使用cr.wipe(obj)方法清理对象,再为obj添加新的属性,就可以达到重复利用对象的目的。虽然通过清空一个对象来获取“新对象”的做法,比简单的通过{}来创建对象要耗时一些,但是在实时性要求很高的代码中,这一点短暂的时间消耗,将会有效的减少垃圾堆积,并且最终避免垃圾回收暂停,这是非常值得的!

2、数组array优化


将[]赋值给一个数组对象,是清空数组的捷径(例如: arr = [];),但是需要注意的是,这种方式又创建了一个新的空对象,并且将原来的数组对象变成了一小片内存垃圾!实际上,将数组长度赋值为0(arr.length = 0)也能达到清空数组的目的,并且同时能实现数组重用,减少内存垃圾的产生。

3、方法function优化


方法一般都是在初始化的时候创建,并且此后很少在运行时进行动态内存分配,这就使得导致内存垃圾产生的方法,找起来就不是那么容易了。但是从另一角度来说,这更便于我们寻找了,因为只要是动态创建方法的地方,就有可能产生内存垃圾。例如:将方法作为返回值,就是一个动态创建方法的实例。

在游戏的主循环中,setTimeout或requestAnimationFrame来调用一个成员方法是很常见的,例如:

setTimeout((function(self) {                    return function () {self.tick();};
})(this), 16)

每过16毫秒调用一次this.tick(),嗯,乍一看似乎没什么问题,但是仔细一琢磨,每一次调用都返回了一个新的方法对象,这就导致了大量的方法对象垃圾!

为了解决这个问题,可以将作为返回值的方法保存起来,例如:

// at startup
this.tickFunc = (function(self) {return function() {self.tick();};}
)(this);// in the tick() function
setTimeout(this.tickFunc, 16);

相比于每次都新建一个方法对象,这种方式在每一帧当中重用了相同的方法对象。这种方式的优势是显而易见的,而这种思想也可以应用在任何以方法为返回值或者在运行时创建方法的情况当中。

4、高级技术


从根本上来说,javascript本身就是围绕着垃圾收集来设计的。随着我们工作的进行,避免内存垃圾变得越来越困难。因为很多方便实用的Javascript库方法也会产生一些新的对象。对于这些库方法产生的垃圾,我们束手无策,只能重新翻看文档,并且检查方法的返回值。例如,数组的slice方法返回一个新的数组(在不修改原数组的基础上,截取出一部分作为新数组),字符串的substr方法返回一个新的字符串(在不修改原字符串的基础上,截取出一部分字符串作为返回值)等等。

调用这些库方法,将会创建内存垃圾,而你能做的,只有避免调用这些方法,或者用不创建系统垃圾的方式重写这些方法(有点极端啦~)。

例如,在Construct2引擎中,从数组中利用下标来删除一个元素,是经常进行的操作。最初我们是用下面这种方式来实现的:

var sliced = arr.slice(index + 1);
arr.length = index;
arr.push.apply(arr, sliced);

然而,slice方法会返回一个新的数组对象(数组中的元素是原数组中删掉的部分),并且会通过arr.push.apply方法将元素重新复制回原数组,但是在此操作之后,该数组就成为了一片内存垃圾。由于这是我们引擎中的垃圾产生的热点代码(使用频率非常很高),因此我们利用了迭代的方式重写了上述代码:

for (var i = index, len = arr.length – 1; i < len; i++)arr[i] = arr[i + 1];
arr.length = len;

显然,重写大量的库函数是非常痛苦的,因此你必须仔细权衡方法的易用性和内存垃圾产生情况。如果产生大量内存垃圾的方法在动画的每一帧中被多次调用,你可能就会兴高采烈的重写库函数啦。

在递归函数中,通过{}构造空对象,并在递归过程中传递数据,虽然是很方便的。但是更好的方式是:利用一个单独的数组对象作为堆栈,在递归过程中对数组进行push和pop操作。更进一步,不要调用array的pop方法(pop将会使得array的最后一个元素将会变成内存垃圾),而应该使用一个索引来记录数组的最后一个元素的位置,在pop时简单的将索引减一即可;类似的,将索引加1来代替array的push操作,只有当索引对应的元素不存在时,才执行真正的push为数组加入一个新元素。

另外,在任何时候,都应该避免使用向量对象(例如:包含x和y属性的vector2对象)。有些方法将向量对象作为方法返回值,既可以支持返回值的再次修改,又能够将需要的属性一次性返回,使用起来非常方便。但是有时候在一帧动画中,创建了成百上千个这样的向量对象,从而导致严重的垃圾回收性能问题,也是非常常见的。因此最好将这些方法分离成具有独立职责的功能个体,例如:利用getX()和getY()方法(返回具体数据)代替getPosition()方法(返回一个vector2对象)。

四、闭包

具体可以看这篇博客:一文了解闭包+闭包

<!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 = 0function inner() {num++console.log(`这是函数调用的第${num}次`)}return inner}let a = outer()a()a()a()num = 21a()</script></body></html>

五、js的math和date

1.math

<!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>console.log(Math.E)console.log(Math.PI)let a = 4.999let b = 3.11// 向下进行取整console.log(Math.floor(a))// 向上取整console.log(Math.ceil(b))console.log(Math.abs(-111))// 最大值最小值console.log(Math.max(1, 21, 32, 12, 21))console.log(Math.min(1, 21, 32, 12, 21))// 随机数  只能取[0,1)console.log(Math.floor(Math.random() * ((20 - 10) + 1)) + 10)// // function get_random(n, m) {//     return Math.floor(Math.random() * ((m - n) + 1)) + n// }// console.log(get_random(100, 200))// 四舍五入console.log(Math.round(3.51))// 开平方根console.log(Math.sqrt(9))// 幂次方console.log(Math.pow(2, 3))</script></body></html>

2.date

<!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>// 实例化时间对象let date = new Date("2024-05-01 00:00:00")console.log(date)// 年let year = date.getFullYear()console.log(year)// 月   0-11let m = date.getMonth() + 1console.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)// 获取毫秒数// let mins = date.getMilliseconds()// console.log(mins)// 时间戳   此刻距离19700101 00:00:00 的毫秒数let timechuo = date.getTime()console.log(timechuo)function get_time() {let date = new Date()let year = date.getFullYear()let m = date.getMonth() + 1let day = date.getDate()let hh = date.getHours()let mm = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes()let ss = date.getSeconds()let w = date.getDay()return `${year}-${m}-${day}  ${hh}:${mm}:${ss}  今天星期${w}`}let a = get_time()console.log(a)</script></body></html>

六、js获取元素对象

1.通过id获取
getElementById() 方法返回带有指定 ID 的元素

  <div id="time"></div>
  <script>
    let time = document.getElementById('time');
  </script>

 2.通过标签名获取
getElementsByTagName()返回带有指定标签名的所有元素的集合。

<p></p>
  <script>
    let p = document.getElementsByTagName('p');
  </script>

 3.通过类名获取
getElementsByClassName() 方法返回带有相同类名的所有 HTML 元素的集合

<div class="box"></div>
  <script>
    let box = document.getElementsByClassName('box');
    console.log(box);
  </script>

 4.通过querySelector()方法获取
querySelector()方法用于返回指定选择器的第一个元素对象

  //1.通过标签名
    let res =document.querySelector('div');
    console.log(res); 
    //2.通过类名
    console.log(document.querySelector('.one')); 
    //3. id选择器
    console.log(document.querySelector('#box')); 
    //4.后代选择器
    let res1 = document.querySelector('ul li');
    console.log(res1); 
    //5.伪类选择器
    console.log(document.querySelector('ul li:nth-child(3)') );
    //6.属性选择器
    document.querySelector('input[name="username"]');

5.通过querySelector()方法获取
querySelecorAlI()方法用于返回指定选择器的所有元素对象集合
(选择器同样指的是css所有选择器,这里就不一一举例了)

console.log(document.querySelectorAll('li'));

 七、js操作元素

1、操作元素


JavaScript的DOM操作可以改变网页内容、结构和样式,我们可以利用DOM操作元素来改变元素里面的内容、属性等。注意以下都是属性

1.1.改变元素内容


 元素.innerText
从起始位置到终止位置的内容,但它去除html标签,同时空格和换行也会去掉

 元素.innerHTML
起始位置到终止位置的全部内容,包括html标签,同时保留空格和换行

1.2.常见元素的属性操作


innerText、innerHTML改变元素内容
arc、href
id、alt、title

1.3.表单元素的属性操作

利用DOM可以操作如下表单元素的属性:

type、value、checked、selected、disabled

4.样式属性操作

通过JS修改元素的大小、颜色、位置等样式。

行内样式操作:

元素.style        //行内样式操作

注意:

  1. JS里面的样式采取驼峰命名法
  2. JS修改style样式操作,产生的是行内样式,权重比较高

类名样式操作: 

元素.className   //类名样式操作

注意:

1.如果样式较多,可以采取操作类名方式更改元素样式
2.class因为是个保留字,因此使用className来操作元素类名属性
3.className会直接更改元素的类名,会覆盖原先的类名
4.如果还想要保留原来的类名:this.className='原来的类名 新加的类名';

5.排他思想


如果有同一组元素,我们想要某一个元素实现某种样式,需要用到循环的排他思想算法:

所有元素全部清除样式
给当前元素设置样式


6.自定义属性操作


element.属性   //获取属性值(元素本身自带的属性)
element.getAttribute('属性')   //主要获取自定义的属性(标准)程序员自定义的属性
设置属性值:
element.属性='值'   //设置内置属性值
element.set Attribute('属性','值')   //主要针对自定义属性
移除属性:
element.removeAttribute('属性');


7.H5自定义属性操作


自定义属性的目的:是为了保存和使用数据,有些数据可以保存到页面中而不用保存到数据库中。

自定义属性获取通过element.getAttribute('属性')

但是有些自定义属性很容易引起歧义,不容易判断是元素的内置属性还是自定义属性。

H5新增了自定义属性:

H5规定自定义属性data-开头作为属性名并且赋值
H5新增的获取自定义属性的方法:element.dataset.index或者element.dataset['index'],ie11才开始支持

八、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><style>div {width: 300px;height: 300px;background-color: pink;}</style>
</head><body><button>点击</button><div></div><script>// 事件:事件源   事件类型    处理函数// l0    on事件类型const button = document.querySelector("button")const box = document.querySelector("div")// 事件源.on事件类型=function(){}  // 同一个事件源,后面注册的事件会对前面注册的事件进行覆盖// button.onclick = function () {//     box.style.display = "none"// }// button.onclick = null// button.onclick = function () {//     console.log("666")// }function text() {alert("666")box.style.display = "none"}// l1  事件监听    不会覆盖button.addEventListener("click", text, true)button.removeEventListener("click", text, true)// button.addEventListener("click", function () {//     // alert("666")//     console.log("444")// }, true)</script></body></html>

练习:距离2024年7月3日还有多久

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>document</title><style>body {font-family: Arial, sans-serif;display: flex;justify-content: center;align-items: center;height: 100vh;background-color: pink;}#aaa {text-align: center;/*水平对齐*/font-size: 24px;}</style>
</head>
<body><div id="aaa">距离2024年7月3日还有:<br><span id="days">0</span>天<span id="hours">0</span>小时<span id="minutes">0</span>分钟<span id="seconds">0</span>秒
</div><script>// 目标日期let mb_Date = new Date('2024-07-03T00:00:00');function updateCountdown() {let dq_Date = new Date();let ch = mb_Date - dq_Date;let days = Math.floor(ch / (1000 * 60 * 60 * 24));let hours = Math.floor((ch % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));let minutes = Math.floor((ch % (1000 * 60 * 60)) / (1000 * 60));let seconds = Math.floor((ch % (1000 * 60)) / 1000);//         使用getElementById方法获取页面上的元素。将获取的元素的文本内容设置为变量的值。document.getElementById('days').textContent = days;document.getElementById('hours').textContent = hours;document.getElementById('minutes').textContent = minutes;document.getElementById('seconds').textContent = seconds;}// 更新倒计时updateCountdown();setInterval(updateCountdown, 1000);// 每隔1秒调用一次 updateCountdown 函数,更新倒计时显示。
</script></body>
</html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/617345.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LRUCache原理及源码实现

目录 LRUCache简介&#xff1a; LRUCache的实现&#xff1a; LinkedHashMap方法实现&#xff1a; 自己实现链表&#xff1a; 前言&#xff1a; 有需要本文章源码的友友请前往&#xff1a;LRUCache源码 LRUCache简介&#xff1a; LRU是Least Recently Used的缩写&#xf…

VMware安装Red Hat7.9

1、下载Red Hat Enterprise Linux7.9版本 【百度网盘下载】 链接&#xff1a;https://pan.baidu.com/s/1567NfZRF48PBXfUqxumvDA 提取码&#xff1a;bm7u 2、在虚拟机中创建Red Hat7.9 【点击创建虚拟机】 【自定义高级】 【选择光盘映像安装】 全名自定义即可 【虚拟机命…

阿里云-Region、VPC、VSwitch、Vrouter

1、Region region是指云资源所在的区域&#xff0c;比如华北3&#xff0c;华东1等等。下图的华北3(张家口)就是 2、VPC VPC&#xff1a;Virtual Private Cloud&#xff0c;简称VPC。基于阿里云创建的自定义私有网络, 不同的专有网络之间二层逻辑隔离&#xff0c;可以在自己创…

Nginx健康检查

Nginx健康检查nginx_upstream_check_module nginx健康检查介绍: ​ 主动健康检查&#xff0c;nignx定时主动地去ping后端的服务列表&#xff0c;当发现某服务出现异常时&#xff0c;把该服务从健康列表中移除&#xff0c;当发现某服务恢复时&#xff0c;又能够将该服务加回健…

图解二叉树遍历方法-前序遍历、中序遍历、后序遍历

一、几个概念 二叉树&#xff08;binary tree&#xff09;&#xff1a;是 n&#xff08;n > 0&#xff09;个结点&#xff08;每个结点最多只有2棵子树&#xff09;的有限集合&#xff0c;该集合可为空集&#xff08;称为空二叉树&#xff09;&#xff0c;或由一个根节点和…

使用Redis实现用户最近浏览记录

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 Redis是一个key-va…

使用VBA巧妙获取图表数据源区域

在日常工作中&#xff0c;使用VBA操作Excel图表是经验遇到的工作创建。 示例图表如下&#xff1a; 使用如下代码可以更新图表的数据源区域&#xff0c;增加一个数据系列。 Sub UpdateChart()ActiveSheet.ChartObjects(1).ActivateActiveChart.SetSourceData Source:Range(&qu…

牛客研究生复试刷题(1)

KY30进制转换 1.最开始没有考虑到大数问题,可以说是没考虑完全,输入类型使用的是int64_t,只ac了一半测试用例。所以在数很大找不到合适的数据类型存储时,要考虑使用string来存放。 2.使用string存放数字的时候就要考虑:字符和数字之间的转换。字符转换成数字:str[i]-0,…

从 0 搭建公司Jenkins服务 Centos7

从 0 搭建公司Jenkins服务 Centos7 安装 (运维人员) 安装环境 配置DNS安装JDK17安装Jenkins安装Docker安装GIT安装Ansible启动Jenkins安装插件配置凭据配置共享库配置 (开发经理)使用 (开发、测试人员) 安装 (运维人员) 安装环境 配置DNS 新安装系统的服务器无法解析域名&a…

CMake 学习笔记2

其他很好的总结 CMake教程系列-01-最小配置示例 - 知乎 CMake 保姆级教程&#xff08;上&#xff09; | 爱编程的大丙 10-补充(完结)_哔哩哔哩_bilibili 1、基本关键字 SET命令的补充 &#xff08;1&#xff09;SET命令设置执行标准 #增加-stdc11 set(CMAKE_CXX_STANDARD…

二、Flask会话技术和模板语言

Cookie Session # views.py: 路由 + 视图函数 import datetimefrom flask import Blueprint, render_template, request, redirect, session from .models import *# 蓝图 blue = Blueprint(user, __name__)# 首页 可以写两个路由,都是访问同一个函数 @blue.route(/) @blue.ro…

【算法基础2】前缀和与差分

目录 前缀和与差分1.综述2.前缀和&#xff08;1&#xff09;一维前缀和&#xff08;2&#xff09;二维前缀和&#xff08;子矩阵的和&#xff09; 3.差分&#xff08;1&#xff09;一维差分&#xff08;2&#xff09;二维差分&#xff08;差分矩阵&#xff09; 前缀和与差分 1…