前言
最近整理代码时,我翻看了前段时间备考蓝桥杯Web组的练习代码。当时,我是跟着蓝桥云课的《JavaScript 基础入门》课程边学边敲的,因此本文涵盖了该课程的大部分内容。我习惯将知识点、遇到的问题以及探究结果嵌入在代码注释中,注释写得非常细致。
为了便于阅读,我将代码按1.1、1.2、2.1等章节分点整理,结构清晰、条理分明,让大家能像读文章一样轻松理解代码。现在,我将这些学习笔记分享给大家,希望能为JavaScript初学者提供帮助,顺便心痛一下那300块钱学费(
全文共800+行,干货满满!
正文
1.html
摘要
DOM事件:点击,双击,移入,移出
DOM节点:为test.js里的dom操作提供div目标
注意
请在浏览器或通过 Live Server 插件打开 1.html,确保 test.js 与 1.html 位于同一目录并已引入,以运行JavaScript代码。同时,1.html 中包含 test.js 的DOM操作所需的关键 div 元素。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 导航栏 -->
<div class="navbar">
<a class="navbarButton" >首页</a>
<!-- 使用querySelectorAll返回的是一个静态Nodelist,要设置color需要历遍..nodelist是类数组型,有length属性,但是没有继承所有的数组方法,以此来避免额外的性能开销..也可以用静态方法Array.from(变量名)转换成数组
nodelist的历遍可以使用forEach方法,
onmouseover="document.querySelectorAll('.navbarButton').forEach(e1 => e1.style.color = 'red')"-->
<a class="navbarButton">HTML</a>
<a class="navbarButton">CSS</a>
<a class="navbarButton">JavaScript</a>
<a class="navbarButton">关于</a>
<a class="navbarButton">帮助</a>
</div>
<!-- 主体 -->
<div class="head1" id="head1">
hahaha
</div>
<div class="forpro">
<h1>输出当前的时间:</h1>
<div id="forpro_timer_divId" class="forpro_timer_divClass"></div>
<div class="forpro_container_divClass" id="forpro_container_divId"></div>
</div>
<div class="dom_par" id="dom_parID" ></div>
<div class="dom_onclick" style="background-color: #ee5844;margin: 0 0 0 0;">
<p
style="margin: 0 0 0 0;"
onclick="this.innerHTML = '我爱学习,身体好好!'"
ondblclick="this.innerHTML = '我爱学习,身体好好好!'"
onmouseover="this.innerHTML = '你把鼠标移到了上面'"
onmouseleave="
this.innerHTML = '你把鼠标移开了';
setTimeout(() => {
this.innerHTML ='请点击文本,双击该文本或把鼠标移动到上面';
}, 1000);">
请点击文本,双击该文本或把鼠标移动到上面</p>
</div>
<!-- 这里p是一个段落,内容会被margin撑大 -->
</body>
<style>
/* 导航栏 */
.navbar{
background-color: #f5f5dc;
display: flex;
gap: 16px;
}
.navbarButton{
text-decoration: none;
color: #2424eb;
display: flex;
gap: 160px;
font-size: 24px;
}
.navbarButton:active{
background-color: red;
}
/* 主体 */
.head1{
/* width: 100%; */
background-color: antiquewhite;
}
.forpro h1{
margin: 0 0 0 0;
background-color: #ffe793;
}
.forpro_timer_divClass{
background-color: #ee5844;
}
.forpro_container_divClass{
background-color: #a6e22e;
height: 320px;
overflow: auto;
}
</style>
<script src="test.js" ></script>
<!-- script最好放在最下面,防止dom找不到元素,或者用defer延迟执行脚本,知道文档加载完毕才执行脚本
同时,放在下面时添加的标签也是添加在下面 -->
</html>
test.js
摘要
变量:动态类型;命名规则
运算符:===;==;类型转换
数组:创建;增删;截取
字符串:查找;截取;替换
类型转换:显式;隐式
函数:声明;自执行;嵌套
对象:字面量;原型链
JSON:键值对;无方法
内置对象:数组;日期;数学
DOM事件:点击;双击;移入;移出
DOM节点:增删改查
BOM:窗口控制;定时器
作用域:函数级;无块级
闭包:保留变量
函数进阶:this绑定;参数处理
注意
以下是 test.js 的代码,依赖 1.html 中的 div 元素进行DOM操作,请通过 1.html 运行。
//1.1 变量
console.log("hello world");
var name = "实验楼";
// 变量必须以字母,下划线,美元符号$头,不能以数字开头
//大小写区分
//动态类型语言,不需要指定变量将包含什么类型
//给一个带引号的值,就是字符串."1"也是字符串,可以用typeof查看类型
/*1.2 运算符
不等于!==
1
*/
/*1.3 数组
创建并赋值数组*/
//var myarray = new Array[1 ,2 ,3 ,4 ,5];
var myarray = [1 ,2 ,3 ,4 ,5];
// 多维数组
var student = [
["张三" ,"男" ,"18"],
["李四" ,"男" ,"220"]
];
student[0][2];
//获取数组长度
var len_stu = student.length;
console.log(len_stu);
//将字符串转化为数组--对字符串使用split()方法
"1:2:3:4".split(":");
"a|b|c".split("|");
//将数组转化为字符串——对数组使用join()方法
myarray.join(":");
myarray.toString(); //也可以使用tostring方法来转换,但是无法指定分隔符,只能是逗号
console.log(myarray);
//在数组尾部添加一个或多个元素,使用push()方法
var arr = ["1" ,"2" ,"3" ,"4"];
arr.push("5" ,"6");
console.log(arr);
// 删除数组的最后一个元素,并把数组的长度减1,用pop()方法
arr.pop();
console.log(arr);
//如果数组为空则不改变数组,然后返回undefined值
var arr_b = [];
arr_b.pop();
console.log(arr_b ,typeof(arr_b));
//在开头添加,用unshift。删除开头,用shift
//1.4 无
//==,相等操作符,比较值是否相等,不比较类型
/*===,全等操作符,比较值和类型是否相等。
比如说,null和undefined的值相等,但是他们的类型不相等
undefined表示所有未赋值变量的默认值
null表示一个变量不在指向任何对象的地址
*/
//1.5字符串
//连接字符串,直接用+
//数字转字符串,使用tostring
var myNum = 9123;
var myString = myNum.toString();
var hello_str = "Hello World";
console.log(typeof(myNum));
//获取长度,继续用length
console.log(myString.length);
//获取字符串第一个字符
console.log(myString[0]);
//查找字符串是否包含某个字词,没找到会返回-1
/*str.indexOf(searchValue, fromIndex);
fromIndex,开始查找的位置,默认为0,fromIndex >= str.length,则返回-1
特殊情况:被查找的字符串为空字符串时,当 fromIndex <= 0 时返回 0,0 < fromIndex <= str.length 时返回 fromIndex,fromIndex > str.length 时返回 str.length
*/
myString.indexOf("9");
//从字符串当中提取用slice(strat,end)
var res1_myString =myString.slice(0,2);
console.log(hello_str);
//转换大小写
/*toLowerCase() ,全部转化为小写
toUpperCase() ,全部转化为大写
*/
var lowercase_hello = hello_str.toLowerCase();
console.log(lowercase_hello);
//替换字符串的某一部分,用replace,注意这个只能替换第一次出现的字符串,要替换的话要用全局替换方式
var replace_hello = hello_str.replace("World" ,"shiyanlou");
console.log(replace_hello);
console.log(hello_str.replace(/o/g ,"hello"));
//1.6转换成字符串
//使用tostring()可以带参,括号内是进制方式
//有的值没有 toString() 方法,所以需要用 String(),比如 null 和 undefined
//1.7 任意值转换成数值类型
//number()可以把任意值转化成数值,如果将转化的字符串里面有一个不是数字的字符,则返回NaN(not a number)
//parseInt()把字符串转化成整数,可带两个参数,(字符串 ,进制)
var num1 = "12";
console.log(parseInt(num1 ,2) ,typeof(num1));
//字符串转换成浮点数,但是只支持十进制数,如果内容只有整数,则解析成整数
console.log(parseFloat(num1));
//隐式类型转换,执行-0操作。如果该字符串不是纯粹的数字字符串,尽管在-0之后,它的数据类型变为number,但是其值为NaN
console.log(typeof("1221" - 0));
NoPureNumTransform = "abc" - 0;
console.log(typeof(NoPureNumTransform) ,NoPureNumTransform);
//1.8 转换成布尔类型
console.log(Boolean(123));
//在控制语句,比如if当中,会将括号里面的条件隐式转换成布尔值
var message; //这句语句中定义了一个messaage变量,但是没有赋值,默认为undefined,它的布尔值为false
console.log(message);
if (message) {
}
else{
console.log("false");
}
//2.1 条件
// 三元表达式 条件表达式?结果1:结果2
//2.2 循环
//continue使得当亲一次循环下的下面的语句都不执行
//2.3 函数
//方法需要依附于对象使用比如说console.log,这是面向对象编程的一个体现
//常规法创建函数
RegularFunction(1 ,2); //这样写没问题,js会把当前作用域的函数声明放到最前面
function RegularFunction(a ,b) {
console.log(a + b);
}
//函数表达式创建函数,比如说上面的可以改编为
var FunExpressFunction = function (a ,b) { /*但是如果用表达式法创建函数,这样就和定义其他基本类型的边框
一样,没什么特殊的,只会按顺序执行,所以就不能把调用放在声明
前面,同时后面的这个function也是一个匿名函数,函数名就是
变量名。要是想不命名直接调用,可以用自调用*/
console.log(a + b);
}
FunExpressFunction(2 ,3);
//js当中,后定义的函数会覆盖之前定义的函数
//如果函数中没有返回值或者return后面没有跟任何值,则默认返回undefined
//匿名函数的自调用,可以避免全局变量污染,原理:()()
(function () {
console.log("self-calling!");
})();
//练习1:打印直角三角形
console.log("\n");
var TimesInp;
//TimesInp = prompt("请输入三角形的行数");
//最好进行显示类型转换,保证逻辑严密
var goal = 10;//prompt("请输入要打印的三角形行数");
goal = Number(goal); //因为prompt获取到的是字符串
console.log(typeof(goal));
if (goal > 10) {
console.log("输入的数字太大了" ,typeof(goal));
}
//3.1 json简介
//在javascript里面所有事物都是对象,字符串,数组,日期等
//属性就是和对象相关的值,也可以理解为特征
//方法就是在对象上执行的动作,也可以理解为行为
//例如,一辆汽车就是现实生活里面的对象,它的名字,它的颜色,它的价格等特征就是汽车对象的属性。它能启动,驾驶,加速刹车就是汽车对象的方法
//3.2 json格式
//json是一种轻量级的数据交换语言
//json源于JavaScript,其数据格式与语言无发热,但是有许多语言都支持json
//json的文件扩展名是.json,官方的MIME类型是application/json
//注意:
//json是一种纯数据格式,它只有属性,没有方法。
//json的属性必须用“ ”引起来
//json要求两头有{}来使其合法
//可以把JavaScript对象原原本本的写入json数据,比如说:字符串,数字,数组,布尔值,还有其他字面值对象
//层级关系:
/*可以用{
[],[]
}
的形式实现多层嵌套,也就是以数组作为顶层结构,实现存放多个对象
也可以用对象存放对象或者混合的方式
{
"student": [],
"age": {}
}
*/
//3.3 常用内置对象
/*1.Array对象,
常用属性:length,获取数组的长度
常用方法:
concat() 方法,用于链接两个或多个数组,并返回结果,语法为
arrayObject.concat(arrayX ,arrayY ,...);
例子:
*/
var ToConcat_a = [1 ,2 ,3];
var ToConcat_b = [4 ,5 ,6];
var ToConcat_c = ["one" ,"two" ,"three"];
console.log(ToConcat_a.concat(ToConcat_b ,ToConcat_c));
//意思就是对象ToConcat_a使用了concat()方法拼接了字符串对象ToConcat_b ,ToConcat_c
//test:2025年1月8日16:45:05
//pop()方法:弹出,删除并返回数组的最后一个元素。
//push()方法:拉长,向数组的末尾添加一个或多个元素,并返回拉长之后数组的长度
//reverse()方法:倒序,颠倒数组的顺序,返回修改后的数组本身
//shift()方法:移除,删除并返回数组的第一个元素,先进先出,队列,其他的元素向前移动.
/*注:队列:有顺序,按时间处理的系统,确保了请求和任务处理的公平性,更符合人类直觉.
在C语言中如果要这样操作,那就需要更改每个位置的元素,所以我们给数组添加顺序一般添加到 末尾,为什么JavaScript能这样?答:JavaScript的数组是动态分的,数组元素在内存中的位置不一定是连续的.数组是对象,对象的属性时可以动态改变的.除外,JavaScript 提供了对数组的高级抽象,背后处理了很多底层细节。可以让开发者不必考虑一些底层问题
*/
//unshift()方法:移除的反义词,添加,向数组的开头添加一个或多个元素,并返回新的长度
//slice()方法:切片,从数组中提取一部分并返回。其中start的值是必需的,规定从何处开始选取。可以为负数。end的值是可选的,规定从何处结束选取,如果没有设置,默认为从start开始选取到数组后面的所有元素。该方法不会修改数组,只会返回值
var slice_a =[1 ,2 ,3 ,4 ,5 ,6];
console.log(slice_a.slice(2 ,5));
//splice()方法,拼接剪接,用于删除或替换当前数组的某些项目.语法为arrayObject.splice(start ,deleteCount ,options);
//其中start的值是必需的,规定删除或替换项目的位置
//deleteCount的值是必需的,规定要删除的项目数量,如果设置为0,则不会删除项目
//option的值是可选的,规定替换它的新项目
//和slice()方法不同的是,splice()方法会修改项目
var splice_s = [1 ,2 ,3 ,4 ,5, 6];
splice_s.splice(2 ,2 ,"abc"); //012从序号为2的元素开始删,删两个,然后把删掉的部分替换为"abc"
//sort()方法,排序,会改变原始数组!,语法为arrayObject.sort(sortby).其中sortby这个参数可选,参数必须为函数,在这个函数中,传入a和b的值,若传出的结果为大于零的数字,则说明前者比后者更靠前。没参数的话,默认按字符编码排序
var sort_arr1 = ["a" ,'z' ,'k' ,'w' ,'x'];
document.write(
`<div class ="sort_arr1_resultDiv" style="background-color : lightblue";>
${sort_arr1}
</div>` ); //注:write方法只能在加载过程中使用,如果使用了defer标签,现代浏览器禁止在文档加载完成后使用document.write
document.getElementById("head1").innerHTML +=
`<div class ="sort_arr1_resultDiv" style="background-color : #007acc";>
${sort_arr1.sort()}
</div>`
//数字排列-从小到大
function sortNum_ByOlder(a ,b){
return a - b; //从小到大排序
}
function sortNum_ByOlderRev(a ,b){
return b - a; //从大到小排序,(b - a)相对于(a - b)来说是绝对值
}
var sort_arr2 = [11 ,55 ,22 ,44 ,66 ,33];
let sort_arr2_div = document.createElement('div');
sort_arr2_div.className = "sort_arr2_divClass";
sort_arr2_div.style.backgroundColor = "#a47aee";
sort_arr2_div.innerHTML += (sort_arr2.sort(sortNum_ByOlder) + "<br \>" );
document.body.appendChild(sort_arr2_div);
//数字排序-从大到小
var sort_arr4 = [1 ,22 ,44 ,6 ,55 ,5 ,2 ,4 ,66];
let sort_arr4_div = document.createElement('div');
sort_arr4_div.className = "sort_arr4_divClass";
sort_arr4_div.style.backgroundColor = "#8eaa85";
sort_arr4_div.innerHTML += (sort_arr4.sort(sortNum_ByOlderRev) + "<br \>");
document.body.appendChild(sort_arr4_div); // appendchild后面放DOM元素
//toString()方法,把数组转化为字符串,并返回结果
/*2.String对象
常用属性:length,获取字符串长度*/
//charAt()方法,获取指定位置处的字符.StringObject.charAt(index);index是下标.字符串的第一个字符的下标是0.如果参数不在0与String.length之间,该方法则返回一个空字符串
var charAt_str = "Hello World!";
let charAt_str_div = document.createElement('div');
charAt_str_div.className = "charAt_str_divClass";
charAt_str_div.style.backgroundColor = "#7762c8";
charAt_str_div.innerHTML += (charAt_str.charAt(2) + "<br \>");
document.body.appendChild(charAt_str_div);
//conct()方法,连接字符串,等效于“+”,“+”,更常用,与数组中的concat()方法类似
var concatstr_a = "hello world!";
var concatstr_b = "shiyanlou";
console.log(concatstr_a.concat(concatstr_b));
//slice()方法,提取字符串的片段,并在新的字符串中返回被提取的部分
//indexof()方法,检索字符串
//toString()方法,返回字符串
//toLowerCase()方法,把字符串转换为小写
//toUpperCase()方法,把字符串转换为大写
//replac()方法,替换字符串中的某些部分
//split()方法,把字符串分割为字符串数组
/*3.Data对象 */
//Date()方法,返回当前的日期和时间
//getDate()方法,从Date对象中返回一个月中的某一天(1-31)
//getDay()方法,从Date对象中返回一周中的某一天(1-6)
//getMonth()方法,从Date对象中返回月份(0-11)
//getFullYear()方法,从 Date对象中以四位数字返回年份
//getHours()方法,返回Date对象的小时(0-23)
//getMinutes()方法,返回Date对象中的分钟(0-59)
//getSecond()方法,返回Date对象中的秒数
//getMilliseconds()方法,返回Date对象中的毫秒(0-999)
/*4.Math对象
常用属性:*/
//E属性,返回常数e(2.7118281828...)
console.log(Math.E.toPrecision(100) ,Math.PI.toFixed(100));
//LN2属性,返回2的自然对数ln2
//LN10属性,返回10的自然对数ln10
//LOG2E属性,返回以2为底的e的对数(log2e)
//LOG10E属性,返回以10为底的e的对数(log10e)
//PI属性,返回π
//SQRT1_2属性,返回1/2的平方根
//SQRT2属性,返回2的平方根
/*常用方法: */
//abs(x)方法,返回x的绝对值
//round(x)方法,返回x四舍五入后的值
//sqrt(x)方法,返回x的平方根
//ceil(x)方法,返回大于等于x的最小整数.ceil天花板向上取整
//floor(x)方法,返回小于等于x的最大整数,floor地板向下取整
//sin(x)
//cos(x)
//tan(x)
//acos(x)
//asin(x)
//atan(x)
//exp(x),exponential指数,返回e的x次幂
//pow(n,m),返回n的m次幂
//log(x)
//max(a ,b),返回a,b中较大的的数
//min(a ,b),返回a,b中较小的数
//random(),返回大于0小于1的一个随机数
console.log(Math.random().toPrecision(50));
//3.4 创建对象和访问对象
//1.通过对象字面量来创建
var literal_student = {
name:"zhangsan" ,
age: 18 ,
gender: "male",
sayHi: function (params) {
console.log("hi , my name is " + this.name);
},
};
//在控制台输入student.gender可以调用对象的属性,输入student.sayHi()可以调查用对象的方法
//通过上面的例子你会发现对象的属性和方法都通过"."来调用
//2.通过new Object()创建对象
var newObject_student = new Object();
(newObject_student.name = "zhangsan"),
(newObject_student.age = 10),
(newObject_student.gender = "male"),
(newObject_student.sayHi = function (params) {
console.log("hi,my nane is" + this.name);
});
//3.通过工厂函数创建对象
function createStudent(name ,age ,gender){ //定义了一个名字叫createStudent的工厂函数。这个函数用来创建和返回一个新的对象
var factory_student = new Object(); /*创建了一个空对象factory_Student..new Object()会返回一个空对象
工厂函数是手动在函数体里面使用new var了一个对象,然后再用return返回了回去(但是也可以在调用的时候在函数名前面加上new关键字来自动创建并绑定),而且由于是在函数体里面创建并返回的,所以每个传入并创建的对象都有独立的内存空间,会比较占内存,如果在工厂函数中定义方法,每个对象实例都会有一份独立的副本,导致较高的内存占用..因此,工厂函数适用于简单的对象创建,但是在需要大量对象共享方法的情况下,使用构造函数+prototype会更加高效
*/
factory_student.name = name; //将传入的值赋值给
factory_student.age = age;
factory_student.sayHi = function (params) {
console.log("hi,my name is" + this.name); //this.name会引用当前对象的name属性
};
return factory_student; //注意返回值..用于返回创建的学生对象
}
var factory_s1 = createStudent("zhangsan" ,18 ,"male");
//4.自定义构造函数来创建对象
function custom_student(name ,age ,gender){ //创建了一个函数,传入name,age,gender
this.name = name;
this.age = age;
this.gender = gender;
this.sayHi = function (params) {
console.log("hi ,my name is " + this.name);
}
}
var s1 = new custom_student("zhangsan" ,18 ,"male"); //当使用关键字new调用一个函数是,会自动创建一个新对象并绑定到this上
//3.5 prototype属性
//什么是prototype? 这是一个属性,指向一个对象,这个对象可以用来存储共享的属性和方法,从而实现对象实例之间的复用..
//每个函数(包括构建函数在创建时,都会自动创建一个prototype属性,该属性指向一个空对象,这个对象的是用来存储可以被共享的属性和方法
//3.6一些关键字
//1.new关键字
//构建函数是一种很特殊的函数.主要用来在创建对象时初始化对象,即为对象成员赋初值,总与new运算符一起用在创建对象的语句中.这里有特别注意的几点:
//*构建函数用于创建一类对象,首字母要大写
//*内部使用this关键字给对象添加初值
//*使用new关键字调用对象构造函数
//2.this关键字
//谁调用this,它就是谁
//函数在执行this时2是不确定的,只有在调用的时候才可以确定
//普通函数被直接调用时(不是通过对象的方法,或者特定绑定),函数内部的this默认指向全局变量.在浏览器环境中,全局变量就是Window
function DefultThis_test(){
console.log(this);
}
//当函数被作为一个对象的方法被该对象调用时,那么this指向的就是该对象
//构造函数中的this,始终是new的当前对象
//3.7 历遍对象的属性
//通过for...in语句用于历遍数组或者对象属性,对数组或对象属性进行循环操作
var cycle_student ={
name :"zhangsan",
age :18, //之所以不使用"",是因为尽管有强制类型转换,但是当使用+运算符的时候,仍然会视为拼接而不是加法,因此应该要明确类型
gender :"male"
};
/*for循环用法:for..in是专门设计用于对象属性遍历的结构,结构为定义一个循环变量用于某个对象,历遍对象中的可枚举属性,并将对象的每个属性名依次赋值给循环变量,然后依次执行循环体
for (var key in object) {
// 在每次迭代时,key 是对象中的一个属性名
// 通过 object[key] 可以访问对应属性值
}
相比于for循环,for..in会自动完成初始化,条件判断,更新操作..
*/
console.log("before delete:");
for (var cycle_key in cycle_student){ /*
注:cycle_key是一个变量,当中存储的是该对象的所有属性的名字*/
console.log("cycle_student." +cycle_key +":" +cycle_student[cycle_key]);
}
//3.8 删除对象的属性
//使用delete操作符删除对象的属性
//delate返回true或flase,被delete的对象不存在时也会返回true,只有对象存在而且有DontDelete属性时才返回flase
console.log("after delete:");
delete cycle_student["name"]; //naem(不加引号)会被认为是一个变量,找不到变量就会删不了..而不加引号表示这是一个属性的名字
delete cycle_student.age; //也可以用点语法
for (var cycle_key in cycle_student){ /*
注:cycle_key是一个变量,当中存储的是该对象的所有属性的名字*/
console.log("cycle_student." +cycle_key +":" +cycle_student[cycle_key]);
}
//3.9 写一个函数,格式化日期对象,最终输入形式为:yyyy/MM/dd HH:mm:ss。
//这里再详细讲解一下date对象。
//在赋值的时候可以new一个date对象,
// 当Date(),也就是没有传入值的时候,此时的return值类似"2025-01-17T13:48:42.491Z"..当有传入值的时候,会把参数格式化为上面的形式
var format_date_Milliseconds = 0;
var format_date_date = new Date();
function format_date() {
format_date_date = new Date();
var format_date_year = format_date_date.getFullYear();
var format_date_mouth = (format_date_date.getMonth() + 1).toString().padStart(2 ,'0'); //pad填充padding,start在开头,padstart在开头填充
var format_date_day = format_date_date.getDate().toString().padStart(2 ,'0');
var format_date_hour = format_date_date.getHours().toString().padStart(2 ,'0');
var format_date_minute = (format_date_date.getMinutes()).toString().padStart(2 ,'0'); //toString()是方法,调用的时候必须加()*2
var format_date_second = format_date_date.getSeconds().toString().padStart(2 , "0");
format_date_Milliseconds = format_date_date.getMilliseconds().toString().padStart(3 ,"0")
return (
format_date_year +
"/" +
format_date_mouth +
"/" +
format_date_day +
" " +
format_date_hour +
":" +
format_date_minute +
":" +
format_date_second +
"\t" +
format_date_Milliseconds
);
}
console.log(format_date());
var forpro_i = 0;
var TextEncoder = document.createTextNode("过去了一毫秒");
var forpro_tiemout = setInterval(
function(){
if (format_date_date.getMilliseconds() != format_date_Milliseconds) { //注意是!=
document.getElementsByClassName("forpro")[0].appendChild(TextEncoder);
}
//因为多个元素可以共享同一个类名,所以通过元素名选择的返回值就是一个数组,在使用是要指定数组的第几个元素
document.getElementById("forpro_container_divId").innerHTML +=
`<pre> ${format_date()}</pre>
`;
forpro_i++;
document.getElementById("forpro_timer_divId").innerHTML = `<p style="font-size: 24px;margin:0 0 0 0;">你发呆了${forpro_i}秒</p>`;
var forpro_container_div_scrollHeight = document.querySelector("#forpro_container_divId").scrollHeight;
document.querySelector("#forpro_container_divId").scrollTop = forpro_container_div_scrollHeight; //在css中,是通过.来选中class,表示该选择器适用于所有拥有该类的元素..在css中,使用#来选中id
} ,1000
);
//3.10 总结
//这节课学习了常用的内置对象 Array对象,String对象,Date对象,Math对象
//还有创建和访问对象
//4.1 web api
//浏览器是一个封装较为完善的软件,它给我们提供了操作浏览器功能和页面元素的接口。在本节中,我们将对这些接口进行学习
//web api 是浏览器提供的一套操作浏览器功能和界面元素的api(bom和dom)。
//4.2 bom简介
//browse Object model 浏览器对象模型,指的是由web浏览器暴露的所有对象组成的表示模型。bom和dom(document Object model文档操作模型)不同,既没有标准的实现,也没有严格的定义,所以浏览器厂商可以自由地实现BOM
//作为显示文档的窗口,浏览器程序将其视为对象的分层集合。当浏览器分析文档时,它将会创建一个对象的集合,以定义文档,并详细说明它应如何显示。浏览器创建的对象称为文档对象,它是浏览器使用的更大对象集合的一部分。此浏览器集合对象统称为浏览器对象模型或BOM
// BOM顶级对象window以及常用的操作方法
//window是浏览器的顶级对象,当调用Window下的属性和方法时,可以忽略window
//对话框
//alert() 显示带有一段消息和一个确认按钮的警告框
//prompt() 显示可提示用户输入的对话框
//confirm()显示一段消息以及确认按钮和取消按钮的对话框
//页面加载事件
//onload
window.onload = function () {
//当页面完成加载时执行
//即当页面完全加载所有内容时(包括图像,脚本文件,css文件等),执行
};
//onunload
window.onunload = function (){
//当用户完全退出页面时执行
};
//获取浏览器宽度
var window_width = window.innerWidth; //窗口内部的宽度,包含浏览器窗口的内容宽度,包括滚动条的宽度,使用在需要获取窗口的总可视宽度时
console.log(window_width + "\n" +
document.documentElement.clientWidth + "\n" + //获取html文档的宽度,即<html>的可见宽度,不包含滚动条的宽度,在当需要精确控制内容宽度而忽略滚动条时使用
document.body.clientWidth); //<body>元素的宽度,可能会被超宽元素撑大,不包含滚动条的信息
//获取浏览器高度
var window_height =window.innerHeight;
console.log(window_height + '\n' +
document.documentElement.clientHeight + '\n' +
document.body.clientHeight);
//定时器
//setTimeout()方法,在指定的毫秒数到达之后执行指定的函数,只执行一次..
//clearTimeout()方法取消由setTImeout()方法设置的timeout
//创建一个定时器,2000毫秒后执行
var timerId = setTimeout(
function(){
console.log("Hello shiyanlou");
} ,2000
);
//取消定时器的执行
clearTimeout(timerId);
// setInterval()方法,设定定时调用的函数,也就是可以按照给定的时间(单位毫秒)周期调用函数,
//clearInterval()方法,取消由setInterval()方法设定的timeout
//创建一个定时器,每隔两秒调用一次
var timerId = setInterval(
function(){
var date = new Date();
console.log(date.toLocaleDateString());
} ,1
);
clearTimeout(timerId)
//4.3 DOM简介
//文档对象模型(document Object Model,简称DOM),是W3C组织推荐的处理可拓展标志性语言的标准编程接口。DOM定义了访问HTML和XML文档的标准。我们这里主要学习HTML DOM。DOM可以吧HTML看成是文档树,通过DOM提供的API可以对树上的节点进行操作
//DOM能改变HTML输出流:在JavaScript中,使用document.write("新设置的内容<p>标签也可以生成</p>")可以直接像html输出流写内容
document.write("<div style = 'background-color:#ce70d6'>新设置的内容<p style='margin:0 0 0 0;' id='p1'>标签也可以生成</p></div>");
//字符串中的双引号会与hrml标签的双引号冲突..对此,可以是使用单引号'来包裹html标签的属性值,或者使用转义,也就是用两个\"p\包裹
//改变HTML内容,使用innerHTML属性改变HTML内容.比如修改标签p中的内容
document.querySelector("#p1").innerHTML = "hello 实验楼";
//改变html属性
document.querySelector("#p1").id = "p2";
try {
document.querySelector("#p1").innerHTML = "hello ";
} catch (error) {
console.log("发生错误,但已忽略:" ,error);
} //会报错选不到,然后会影响后续代码的执行
// DOM节点
//根据W3C的html dom标准,html文档中的所有内容都是节点:整个文档就是一个文档节点,而每个HTML标签都是一个元素节点。html标签中的文本则是文本节点,html标签;则是属性节点,一切都是节点
//document-文档节点-整个文档 window.document
//documenttype-文档类型节点-文档的类型
//element-元素节点-html元素(比如<body><div>等)
//attribute-属性节点-html元素的属性(比如class="right")
//text-文本节点-html文档中出现的的文本
//documentfragment-文档碎片节点-文档的片段
//Dom节点的操作
//获取节点
//要操作节点,首先我们要找到节点.主要有以下三种方法:
//1.通过id找到html元素
//2.通过标签名找到html元素:使用方法getELementByTagName()来选取元素..如果有多个同类型标签那么我们可以通过下标来确认,比如:
document.getElementsByTagName("div")[0];
//下标为[0]表示选取第一个div标签,
document.getElementsByTagName("div")[1];
//下标为[1]表示选取第2个div标签
//3.通过类名来找到html标签
//使用方法getElementsByClassName()通过元素的类名来选取元素
console.log( document.getElementsByClassName("forpro_container_divClass"));
//返回包含class="name"的所有元素的一个列表
//DOM节点之间的关系
//DOM的节点并不是孤立的,我们从DOM树中可以看出,节点和节点之间存在相对关系,就如同一个家族一样,有父辈,有兄弟,有儿子等.下面我们来看一下有哪些节点:
//父节点 parentNode
//兄弟节点 nextSibiling nextELementSibiling previousSibiling previousELementSibiling
//子节点 firstChild firstELementChild lastChild lastELementChild
//所有子节点 childNodes children
//例如,在下面这个文档中
/*<html>
<head>
<title>DOM 节点演示</title>
</head>
<body>
<h1>我是h1标签</h1>
<p>我是p标签</p>
</body>
</html> */
//<html>节点没有父节点,它是根节点
//<head>和<body>的父节点是<html>节点
//文本节点 我是p标签 的父节点是<p>节点
//<html>节点有两个子节点<head>和<body>
//<h1>节点和<p>节点是兄弟节点,同时也是<body>的子节点
//需要注意以下几点:
//childNodes 它是标准属性,它返回指定元素的子元素集合,包括html节点,所有属性,文本节点
//children 非标准属性,它返回指定元素的子元素集合.但让只返回html节点,甚至不返回文本节点
//nextSibiling和preViousSibiling获取的是节点,获取元素对应的属性是nextELementSibiling和previousELementSibiling
//nextELementSibiling和previousELementSibiling有兼容性问题,Ie9以后才支持
//DOM节点的操作
//1.创建节点
//创建元素节点,使用createELement()方法.比如
var dom_par = document.createElement("p");
// 创建属性节点,使用createAttribut()方法
var dom_par_attr = document.createAttribute("background-color:red");
dom_par.setAttribute("style" ,"margin:0 0 0 0"); //属性是附加到元素节点上的,不属于子节点,不能用append..append是用来插入子节点的..要用setAttribute()..而margin不是属性名,是css的一个字符串,提到style的时候,后面要直接跟一个字符串作为样式的参数。或者用点语法对创建出来的或选中的div的style进行修改
//创建建文本节点,使用createTextNode()方法
var dom_par_node = document.createTextNode("hhh");
//2.插入子节点
// appendChild()方法向节点添加最后一个子节点
document.querySelector("#dom_parID").append(dom_par); //appendChild是较早的api,兼容性强。但是一次只能添单一节点,而append可以添加多个节点,而且可以添加字符串文本
//insertBefore(goal_node ,point_node)方法在指定的子节点前面插入新的子节点..如果第二个参数没写或者为null,则默认插入到后面
//3.删除节点
//使用removeChild()方法.写法为
//父节点.removeChild(子节点);
//node.parentNode.removeChild(node); 如果不知道父节点是什么,可以用点语法获取,也就是可以这样写
//4.替换子节点
//使用replaceChild()方法.语法为:
//node.replaceChild(newnode ,oldnode) //后面是被替换的目标
//5.操作节点的属性
//获取getAttribut(属性名);
//设置setAttribut(name ,value);
// dom_par.setAttribute(dom_par_attr)
//删除removeAttribut(name);
console.log(document.querySelector("#dom_parID").getAttribute("id"));
//DOM事件
//事件的定义
//在什么时候执行什么事
//事件三要素
//事件由事件源 +事件类型 +事件处理程序 组成
//事件源:触发事件的元素
//事件类型:触发事件的方法(比如鼠标点击或键盘点击)
//事件处理程序:事件触发以后要执行的代码
//常用的事件
//onclick onclick鼠标单击
//ondbclick ondbclick鼠标双击
//onkeyup onkeyup按下并释放键盘上面的一个按键时触发
//onchange onchange文本内容或下拉菜单中的选项发生改变
//onfocus onfocus获得焦点,表示文本框等获得焦点..配合失去焦点使用,可以做到仅在获得焦点的时候显示提示信息
//onblur onblur失去焦点,表示文本框等失去焦点
//onmouseover onmouseover鼠标悬停,即鼠标停留在图片等的上方
//onmouseout onmouseout鼠标移出,即离开图片等所在的区域
//onload onload网页文档加载事件
//onunload 关闭网页时
//onsubmit 表单提交时
//onreset 重置表单时
//5 值类型和引用类型及其异常
//5.1值类型和引用类型
//值类型
//以下变量中存储的是对应的值,值和变量名都存储在栈中
//值类型又叫基本数据类型,原始类型,在JavaScript中值类型有以下五种
//数据类型
//布尔类型
//undefined
//null
//字符串
var Primitive_num = 18;
var Primitive_flag = true;
var Primitive_un = undefined;
var Primitive_nu = null;
var Primitive_str = "zhangsan";
//引用类型
//引用类型又称复合数据类型,在JavaScript中引用类型有以下三种
//对象
//数组
//函数
//引用类型存储在堆中
//变量名存储在栈中,里面的值是地址,指向存储对象的内存处
var Reference_arr = [1 ,2 ,3];
var Reference_p = {
name :"张三",
age :18
};
//5.2 值类型和引用类型的特征
//值类型的特征
//值类型的值是不可变的,不可变指的是值类型指向的空间不可变,例如
var Primitive_a = 2;
/*JavaScript 在栈内存中为变量 a 分配空间,并将值 2 存储在栈上的一个地址位置(假设是地址 A)。
然后a 变量现在指向这个地址 A,也就是存储 2 的位置*/
Primitive_a += 2;
console.log(Primitive_a);
//也就是a变量指向的地址值变了,但是内存中2的地址值没有变
//按值传递的变量之间互不影响,比如
var Primitive_b = Primitive_a;
/*JavaScript复制了一份a的值到其他地方,然后让b指向这个地方 */
Primitive_a = Primitive_a + 2;
console.log(Primitive_a ,Primitive_b);
//再看下面一段代码
console.log(Reference_p.name ,Reference_p.age);
var Reference_p1 = Reference_p;
Reference_p1.name = "李四";
console.log(Reference_p.name ,Reference_p.age)
/*因为Reference型变量存储的是地址,复制的时候也仅仅是把地址复制了一份,所以改变p1指向的对象的内容也改变了p指向的对象的内容。*/
function foo(o){
o.age += 1; //注意,当数据类型为字符串时,哪怕用+=1,也是在字符串后面加上“1”这个字符
}
foo(Reference_p);
console.log(Reference_p.age);
/*同样地当参数为引用类型时,函数内和函数外的两个变量不同,但是共同指向同一个对象,在函数修改对象数据时会影响外部
注:其实我们可以这样理解。引用数据类型中的地址是一把钥匙,钥匙指向的是宝藏,复制一把钥匙后,两把钥匙打开的是同一个宝藏 */
//5.3 调试工具的使用
//在调试的时候,可以加一句console.log()语句来打印出来
//设置断点,逐步运行
//设置断点的方案很简单,直接左键点击代码旁边的数字行数
//选中右键选择将变量加入watch窗口,实时查看它的值的变化
//然后刷新,点击运行,可以逐段运行代码
//5.4 异常处理
//当出现错误时,JavaScript引擎通常会停止,并生成一个错误信息
//异常捕获
//可以使用try-catch语句捕获异常
try {
//这里写可能出现异常的代码
} catch (error) { //给错误信息赋个形参
//执行的代码
}
//注意:
//语句try和catch是成对出现的
//如果在try中遇到了错误,try里面出现错误的语句后面的代码都不执行,直接跳转到catch中,catch处理错误的信息
//如果try中没有出现错误,则不会执行catch中的代码,执行完try中的代码直接执行后面的代码、
//在try或catch执行完以后,代码会继续执行,不会中断
//throw语句
//通过throw语句,我们可以创建自定义错误。throw语句通常和try catch语句一起使用
//7 函数进阶
//在前面的课程中,我们已经学习了一下这些函数的相关内容:函数声明,函数表达式和function()构造函数,以及函数的参数,返回值,调用..现在我们将继续学习函数进阶的内容..
//7.1 call apply bind
//在学习call(),apply(),bind()方法之前,我们先来复习一下this的指向性问题,我们前面说过一个口诀:谁调用this,它就指向谁..让我们先来看一个例子
function this_foods() { }
this_foods.prototype = {
price: "¥15",
say: function () {
console.log("My price is" + this.price);
}
};
var this_apply = new this_foods();
this_apply.say();
var this_orange = new this_foods();
this_orange.say();
//也就是说上述例子调用say()方法,最后打印的结果都是一样的,但是如果我们想打印橘子的价格是10元呢?又不想重新定义say()方法..JavaScript为我们专门提供了一些函数方法来帮我们更优雅第处理函数this指向问题..这就是我们接下来要学习的call() ,apply() ,bind()三个函数方法
//call
//call()方法调用一个函数,其具有一个指定的this值和分别地提供的参数(参数的列表)..语法为
//fun.call(thisArg ,arg1 arg2)
//注: thisArg指的是在fun函数中指定的this的值..如果指定了null或者undefined,则内部的this指向window,同时,值为原始值(数字 ,字符串 ,布尔值)时,this会自动指向原始值,是一个可选项
//arg1 ,arg2 ,...指定的参数列表,也是可选项
//
//call()允许为不同的对象分配和调用属于一个对象的函数/方法..你可以使用call()来实现继承:写一个方法,然后让另外一个新的对象来继承它(而不是在新的对象中在写一次这个方法)
//1.使用call()方法调用函数并指定上下文的this..前面的例子可以写成
var this_apple = new this_foods();
this_orange = {
price: "¥10",
}
this_apple.say.call(this_orange); //使用call让console.log("My price is" + this.price);里面的this指向this_orange
//2.在一个子构造函数中,你可以通过调用父构造函数的call()方法来实现继承
//
//apply
//apply()方法和call()方案类似,唯一的区别是call()方法接受的是参数,apply()方法接受的是数组,语法为
//fun.apply(thisArg ,[argsArray]);
//例子:
var apply_array = ["a" ,"b" ,"c"];
var apply_nums = [1 ,2 ,3];
apply_array.push.apply(apply_array ,apply_nums);
//注:使用concat()方法链接数组,不会改变数组,而是创建一个新数组..而使用push()是接受可变数量的参数的方式来添加元素..使用apply则可以链接两个数组..使用apply是为了将指定的数组变更为这两个数组
console.log(apply_array);
//bind
//bind()方法创建一个新的函数(称为绑定函数),在调用时设置this关键字作为提供的值
//bind()方法用于绑定到一个函数,当绑定函数被调用时,参数thisArg会作为原函数运行时的this指向
//递归
//在函数中,递归就是自己直接或间接的调用自己
//例子:计算1到10之间 的整数相加的和
function recurrence_foo(n){
if(n==0){
return 0;
}else{
return n+recurrence_foo(n-1);
}
}
var recurrence_a = recurrence_foo(10);
console.log(recurrence_foo(10));
console.log(recurrence_a);
//7.2 作用域
//作用域就是变量和函数的课访问范围
//在JavaScript中是没有块级作用域 的,即不会把{}扩在一起的代码视为一个作用域,例如
{
var block_num = 123;
{
console.log(block_num);
}
}
console.log(block_num);
//7.3 闭包
//7.4 arguments对象
//在函数代码中,使用特殊对象argument,无需明确指出变量名,我们就能访问它们..第一个参数是argument[0] ,第二个参数是argument[1] ,以此类推..比如:
function arguments_foo(params) {
console.log(arguments[0]); //取传入参数的第一个
console.log(arguments[1]);
}
arguments_foo(2 ,3); //打印2 3
//还可以用arguments对象检测函数参数个数,引用argument.length即可..来看一个历遍参数求和的例子
function arguments_add(){
var arguments_sum = 0;
for(var i = 0;i < arguments.length;i++){
arguments_sum += arguments[i];
}
console.log("参数的个数为:" + arguments_sum);
}
arguments_add(); //0
arguments_add(1); //1
arguments_add(1 ,2); //3
arguments_add(1 ,2 ,3); //6
//7.5 function对象
//function()对象创建函数的语法如下
//var function_name = new Function(arg1 ,arg2 ,... ,argN ,Function_body)
//注意:每个参数都必须是字符串,Function_body是函数主体..
//直接new一个Function出来,直接把参数和函数体都塞进去
希望这些笔记对你有所帮助,感觉不错的话,动手点个赞吧,祝学习顺利。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。