批改状态:合格
老师批语:总结不错, 可以关注一下异步函数
Javascript 作为一门强大的脚本语言,主要是用于前端开发。相比于其他脚本语言来讲,是有一定难度,所以要想学好它就必须下足功夫。对于如何学好一门语言想必大家都有各自的一套办法,但是方法再五花八门,有一点一定是相同的——那就是打好基础!下面来介绍五个重要的基础知识:
- js 循环
- js 函数
- dom 操作
- classList 对象的使用
- dataset 对象的使用
循环:只要满足条件,将不断的执行重复的语句
入口判断型,循环前先判断括号内条件符不符合要求,如果符合要求则执行代码块中语句
while (condition) { //do something... }
//初始化执行条件let i = 0;//因为i=0不符合要求,大括号中代码不执行while (i > 10) {console.log(i);i--;}// i<10符合要求,括号内代码执行while (i < 10) {console.log(i); // 0,1,2,3,4,5,6,7,8,9i++;}
出口判断型。不管条件如何,至少执行一次循环体。
do { //do something... } while (condition);
//初始化执行条件let j = 0;// 条件不符合,只执行一次大括号内代码do {console.log(j); // 0} while (j > 10);console.log("-------------------");//条件符合,正常执行代码do {console.log(j);j++;} while (j < 10); // 0,1,2,3,4,5,6,7,8,9
计数型: 可视为 while 的简化版本
执行流程是: a,初始化执行条件;b,判断条件是否符合要求.符合继续往下执行,不符合立即停止执行;c,执行完计数+1
for (let i = 0; i < num; i++) {//do something...}
// 不符合条件不执行// for (let k = 0; k > 10; k--) {// console.log(k);// }//可以再括号内和括号外初始化执行条件// let k = 0;// for (k; k < 10; k++) {for (let k = 0; k < 10; k++) {console.log(k); //0,1,2,3,4,5,6,7,8,9}
遍历对象中的允许遍历的属性(枚举的属性)
也可以用来遍历数组,但是一般不用,遍历数组可以用for of
for (let prop in object) { //do something... }
const obj = {name: "zhangshan",age: 20,sex: "male",};for (let prop in obj) {// console.log(prop);//console.log(obj.prop); //undefined (这里面用`.`获取属性名是不行的,必须用`[]`)console.log("属性:", prop, " 值:", obj[prop]);}console.log("-------------------");//遍历数组const arr = ["a", "b", "c"];for (let index in arr) {// console.log(prop);//console.log(obj.prop); //undefined (这里面用`.`获取属性名是不行的,必须用`[]`)console.log("下标:", index, " 值:", arr[index]);}

用于遍历数组
注意:不能直接遍历对象,会报错
Array.forEach(function (value, index, array) { //do something... });
value:遍历的当前元素
index:当前索引
array:正在操作的数组
// 不能直接遍历对象// const user = {// name: "zhangshan",// age: 20,// sex: "male",// };//报错 Uncaught TypeError: user.forEach is not a function// user.forEach((value, key, user) => {// console.log("属性:", key, "值:", value, "对象:", array);// });//遍历数组const array = [1, 2, 3, 4];array.forEach((value, index, array) => {console.log("键:", index, "值:", value, "数组:", array);});

es6 后用于遍历数组
只能用于遍历数组
for (const iterator of object) { //do something... }
const fruits = ["apple", "peach", "pear", "banana"];for (let fruit of fruits) {console.log("水果:", fruit);}

- 相同点
forEach 和 map 用法类似,都可以遍历到数组的每个元素,而且参数一致- 不同点
forEach() 方法对数组的每个元素执行一次提供的函数。总是返回 undefined
map() 方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。返回值是一个新的数组
// forEachconst retForEach = array.forEach((v) => {return v * 10;});console.log(retForEach); //undefined// mapconst retMap = array.map((v) => {return v * 10;});console.log(retMap); // [10, 20, 30, 40] (返回一个新的数组)

循环参考博客:https://www.cnblogs.com/amujoe/p/8875053.html
把一段需要重复使用的代码,用 function 语法包起来,方便重复调用,分块和简化代码
JavaScript 函数是被设计为执行特定任务的代码块。
JavaScript 函数会在某代码调用它时被执行。
声明一个函数有三种方式:函数名,函数表达式,箭头函数
//最常见的方式function foo(val) {//do something...}//函数表达式(匿名函数)const foo = function (val) {//do something...};//箭头函数() => {//do something...};
函数的调用通常都是一个函数名加一个(),但是匿名函数可以(function(){})()这种方式调用。
//调用foo();//函数表达式的调用(匿名函数)foo();//箭头函数(() => {console.log("这是箭头函数的调用");})();
形参
全称为”形式参数” 由于它不是实际存在变量,所以又称虚拟变量。是在定义函数名和函数体的时候使用的参数,目的是用来接收调用该函数时传入的参数。
.在调用函数时,实参将赋值给形参。因而,必须注意实参的个数,类型应与形参一一对应,并且实参必须要有确定的值。
实参
全称为”实际参数”是在调用时传递给函数的参数。
实参可以是常量、变量、表达式、函数等, 无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值, 以便把这些值传送给形参。 因此应预先用赋值,输入等办法使实参获得确定值。
// 函数传参function bar(val) {console.log(val);}let name = "小明";bar(name);// 输出:小明
代码段 function bar(val) 中的 val 是形参。函数调用表达式 bar(name) 中的 name 是实参。
默认参数
默认参数指的是当函数调用中省略了实参时自动使用的一个值
// 默认参数function barz(val1, val2 = "world") {console.log(val1, val2, "!");}barz("hello");//输出 hello world !(调用时省略了一个参数)barz("hello", "小明");//输出 hello 小明 !
剩余参数(重点)
使用剩余运算符,
...rest,...rest将剩余参数全部打包到一个数组变量中
一般情况,当我们要向函数传多个参数时,要一个一个写进去。有时候还会遇到参数个数改变的情况
function show(val1, val2, val3, val4, val5) {console.log("我喜欢的水果是:", val1, val2, val3, val4, val5, "!");}show("apple", "orange", "peach", "bannan", "watermelon");// 输出:我喜欢的水果是: apple orange peach bannan watermelon !
这样写非常费力,而且代码也不美观,没逼格
这时候就可以用...rest了。
//...restfunction show(val1, ...val2) {let str = "我喜欢的水果是:";for (let v of val2) {str += " " + v;}console.log(str + "!");}show("apple", "orange", "peach", "bannan", "watermelon");// 输出:我喜欢的水果是: apple orange peach bannan watermelon !show("apple", "orange");// 输出:我喜欢的水果是: apple orange !
这样是不是代码逼格瞬间提升了几个档次?
不仅如此,我们还可以传随意个数的实参都没问题。
...rest 不仅美观还实用,真的太好了。
与...rest 类似的用法还有...spread 展开运算符。
展开运算符(重点)
...spread 将数组展开成一个个独立的单元.
...rest , ...spread 语法的形式完全一样,怎么区别....name 用在函数的参数中就是将所有参数打包到一个数组...name用在函数的调用参数就是展开操作
function info(name, tel, email, sex) {console.log(name, tel, email, sex);}const user = ["zhangshan", "13888888888", "zhangshan@qq.com", "male"];// 不用展开形式info(user);// 输出:(4) ["zhangshan", "13888888888", "zhangshan@qq.com", "male"] undefined undefined undefined// 展开形式info(...user);// 输出: zhangshan 13888888888 zhangshan@qq.com male
如图

匿名函数顾名思义指的是没有名字的函数,在实际开发中使用的频率非常高!也是学好 JS 的重点.
函数表达式声明一个匿名函数
//匿名函数的声明const callback = function () {//输出函数名字console.log(callback.name);};
正常调用
// 调用callback();
有时我们不用函数表达式也可以声明一个匿名函数
(function(){})
调用
(function(){})()
匿名函数多用作回调函数
// 用于回调// 每5秒输出当前的时间setInterval(function () {console.log(new Date().toLocaleTimeString());}, 5000);
如图

ES6 标准新增了一种新的函数:Arrow Function(箭头函数)
为什么叫 Arrow Function?因为它的定义用的就是一个箭头
箭头函数相当于匿名函数,并且简化了函数定义。
声明一个箭头函数
x => x+2
上面的函数相当于
function (x) {return 2 * x;}
箭头函数相当于匿名函数,并且简化了函数定义。箭头函数有两种格式,一种像上面的,只包含一个表达式,一行代码,连{ ... }和return都省略掉了。还有一种可以包含多条语句,这时候就不能省略{ ... }和return
(x) => {if (x > 0) {return x * x;} else {return -x * x;}};
如果参数不是一个,就需要用括号()括起来
// 两个参数:(x, y) => x * x + y * y// 无参数:() => 3.14// 剩余参数:(x, y, ...rest) => {var i, sum = x + y;for (i=0; i<rest.length; i++) {sum += rest[i];}return sum;}
注意:箭头函数中没有自己的 this
箭头函数博文参考:https://www.cnblogs.com/lfxiao/p/9360238.html
在开始之前我们应该了解一个新的概念就是:类数组。
什么是类数组?
就是一个拥有数组的length属性和从 0 开始递增的索引,但不能直接使用数组所具有的方法的一个对象。
其本质还是对象,它的原型是Object而非Array。
语法: document.getElementsByTagName(tagName)
返回: 根据标签名所匹配到的所有元素的名为HTMLCollection的类数组。
html 源码
<ul><li class="get-dom">item1</li><li class="get-dom">item2</li><li class="get-dom" name="third">item3</li><li class="get-dom">item4</li><li class="get-dom" id="item5">item5</li><li class="get-dom">item6</li><li class="get-dom">item7</li><li class="get-dom">item8</li></ul>
js 源码
//根据tag获取doms// 获取ullet ul = document.getElementsByTagName("ul");console.log(ul);console.log(ul[0]);console.log("----------------------");//获取lilet li = window.document.getElementsByTagName("li");console.log(li);console.log(li[2]);console.log(li[2].innerHTML);console.log("----------------------");
结果

注意:它返回的是一个多个数的
Collection,而不是单个元素。因此,要得到单个元素得用获取数组元素的办法——用[索引]。
id属性获取 dom 对象语法: document.getElementById(id属性名)
返回: 根据id属性名所匹配到的单个元素对象。
js 源码
// 根据id获取doms// 括号内是id名而不是id选择器(#item5)let byId = document.getElementById("item5");// 返回单个的值,非类数组console.log(byId);console.log(byId.innerHTML);
结果

注意:括号内是 id 名而不是 id 选择器(#item5)。
类名获取 dom 对象语法: document.getElementsByClassName(类名)
返回: 根据元素类名所匹配到的所有元素的名为HTMLCollection的类数组。
js 源码
//根据类名获取元素,返回类数组let byClassName = document.getElementsByClassName("get-dom");console.log(byClassName);console.log(byClassName[1]);console.log(byClassName[1].innerHTML);
结果

注意:返回的是一个类数组。
name属性名获取 dom 对象语法: document.getElementsByName(name属性名)
返回: 根据元素name属性名所匹配到的所有元素的名为NodeList的类数组。
js 源码
//根据 name 属性名获取元素let byName = document.getElementsByName("third");console.log(byName);console.log(byName[0]);console.log(byName[0].innerHTML);
结果

注意:返回的是一个类数组。
单个元素对象语法: document.querySelector(选择器)
返回: 返回匹配的集合中的第一个元素。
js 源码
//根据选择器获取ul元素let mySelector = document.querySelector("li");// 获取到的是一组数据中的第一个console.log(mySelector);console.log(mySelector.innerHTML);// 根据伪类选择器获取最后一个子元素对象let lastChild = document.querySelector("ul>li:last-child");console.log(lastChild);console.log(lastChild.innerHTML);
结果

注意:根据选择器获取元素,括号内可以使用伪类选择器。
所有元素语法: document.querySelectorAll(选择器)
返回: 返回包含匹配集合中所有元素的名为NodeList的类数组。
js 源码
//根据选择器获取匹配的所有元素let childs = document.querySelectorAll("ul>li");console.log(childs);console.log(childs[0]);console.log(childs[0].innerHTML);
结果

注意:返回的是一个类数组。
DOM 可以将任何 HTML 描绘成一个由多层节点构成的结构。
节点分为 12 种不同类型,每种类型分别表示文档中不同的信息及标记。
每个节点都拥有各自的特点、数据和方法,也与其他节点存在某种关系。
节点之间的关系构成了层次,而所有页面标记则表现为一个以特定节点为根节点的树形结构。

节点中的各种关系可以用传统的家族关系来描述,相当于把文档树比喻成家谱。
现在以一段 html 代码为例,讲解他们之间的”族谱”关系。
<ul><li class="relation">item1</li><li class="relation">item2</li><li class="relation">item3</li><li class="relation">item4</li><li class="relation">item5</li><li class="relation">item6</li></ul>
以某个元素节点为参考,这个元素节点下面所有的节点都是这个元素的子元素。
例如上面的代码片段中,以<ul>为参考, 下面的<li>都是<ul>的子元素。
子元素相关属性
childNodes
childNodes 是一个只读的类数组对象NodeList对象,它保存着该节点的第一层子节点
// childNodes// 获取参照元素 ulconst ul = document.getElementsByTagName("ul")[0];console.log(ul);// 获取ul的子节点const result = ul.childNodes;console.log(result);
结果

children
children 是一个只读的类数组对象 HTMLCollection 对象,但它保存的是该节点的第一层元素子节点
// childNodes// 获取参照元素 ulconst ul = document.getElementsByTagName("ul")[0];console.log(ul);//children// 获取ul的元素子节点const elemChild = ul.children;console.log(elemChild);
结果

children.length | childElementCount
子元素的数量
js 源码
// 获取子元素的长度// children.lenghtlet childLenght = ul.children.length;console.log(childLenght); // 6// childElementCountlet childCount = ul.childElementCount;console.log(childCount); // 6
这两个属性返回的值是一样的。
firstChild | firstElementChild
第一个子节点 | 第一个元素子节点
// 获取参照元素 ulconst ul = document.getElementsByTagName("ul")[0];// 获取第一个子节点let firstNode = ul.firstChild;console.log(firstNode); //#test// 获取第一个元素子节点let firstElement = ul.firstElementChild;console.log(firstElement);
结果

lastChild | lastElementChild
最后一个子节点 | 最后一个元素子节点
// 获取参照元素 ulconst ul = document.getElementsByTagName("ul")[0];// 获取最后一个子节点let lastNode = ul.lastChild;console.log(lastNode); //#test// 获取最后一个元素子节点let lastElement = ul.lastElementChild;console.log(lastElement);
结果

兄弟元素
以某个元素节点为参考,这个元素相邻的同级元素就是这个元素的兄弟元素。
例如上面的代码片段中,以<li>item3</li>为参考, 相邻的<li>item2</li> 和 <li>item4</li>都是<li>item3</li>的兄弟元素。
兄弟元素相关属性
previousSibling | previousElementSibling
前一个节点 | 前一个元素节点
// 获取第三个lilet thirdLi = document.querySelector("ul>li:nth-of-type(3)");// console.log(thirdLi);// console.log(thirdLi.innerHTML);// 获取前一个节点let preNode = thirdLi.previousSibling;console.log(preNode);// 获取前一个元素节点let preElement = thirdLi.previousElementSibling;console.log(preElement);console.log(preElement.innerHTML);
结果

nextSibling | nextElementSibling
后一个节点 | 后一个元素节点
// 获取第三个lilet thirdLi = document.querySelector("ul>li:nth-of-type(3)");// console.log(thirdLi);// console.log(thirdLi.innerHTML);// 获取后一个节点let nextNode = thirdLi.nextSibling;console.log(nextNode);// 获取后一个元素节点let nextElement = thirdLi.nextElementSibling;console.log(nextElement);console.log(nextElement.innerHTML);
结果

父元素
以某个元素节点为参考,这个元素的上级元素就是这个元素的父元素。
例如上面的代码片段中,以<li>为参考, 上面的<ul>是所有<li>的父元素。
父元素相关属性
parentNode
每个节点都有一个 parentNode 属性,该属性指向文档树中的父节点。对于一个节点来说,它的父节点只可能是三种类型:element 节点、document 节点和 documentfragment 节点。如果不存在,则返回 null
// 获取第三个lilet thirdLi = document.querySelector("ul>li:nth-of-type(3)");// console.log(thirdLi);// console.log(thirdLi.innerHTML);// 获取当前节点的父节点let pNode = thirdLi.parentNode;console.log(pNode);
返回
ul元素。
parentElement
与 parentNode 属性不同的是,parentElement 返回的是父元素节点
// 获取第三个lilet thirdLi = document.querySelector("ul>li:nth-of-type(3)");// console.log(thirdLi);// console.log(thirdLi.innerHTML);// 获取当前节点的父元素节点let peNode = thirdLi.parentElement;console.log(peNode);
返回
ul元素。
dom 元素关系博文参考:https://www.cnblogs.com/xiaohuochai/p/5785297.html
前面我们知道,通过document对象的方法匹配到的多个元素都是以类数组返回,因此我们遍历 dom 元素的思路就是:先取得 dom 元素的 类数组 然后想办法把它转为数组后,我们就可以用遍历数组的方法遍历 dom 元素了。
正好 js 数组原型 给我们给我们提供了一个方法:Array.from() 可以把 类数组转换为数组。
// dom遍历子元素// 如何遍历dom元素// 思路:把其转为数组或者对象再用遍历数组或对象的方法遍历它// 先获取一个元素的类数组const lis = document.querySelectorAll("li");// 把类数组转为数组Array.from()const lisArr = Array.from(lis);// console.log(Array.isArray(lisArr)); //true//遍历forEach()/for of// forEach()lisArr.forEach((e) => {// 文本字体变红e.style.color = "red";});// for offor (let e of lisArr) {// 给父元素加边框if (e.parentElement.hasChildNodes(e)) {e.parentElement.style.border = "1px solid #000";break;}}
结果

classList 对象是用来操作元素的 class 的。
之前我们要想改变一个元素的class值有两种方法:
style 属性
className 属性
这两个都可以改变一个元素的class属性,但是有一个区别是style改变的是 class 的行内样式,它的优先级要比className属性要高。而且操作起来不够灵活。
要知道详情可以访问博文:https://blog.csdn.net/sinat_32017511/article/details/86497912
现在有一个可以操作元素类属性的对象可以用了:classList;
该
Element.classList是一个只读属性,返回现场DOMTokenList的集合class元素的属性。然后可以使用它来操作类列表。使用
classList是通过空格分隔的字符串访问元素的类列表的便捷替代方法element.className。
下面通过实例演示classList对象的几种常用的方法
css 源码
/* 样式初始化 */* {margin: 0;padding: 0;box-sizing: border-box;}/* 变紫色 */.rebeccapurple {background-color: rebeccapurple;}/* 变成灰色 */.gray {background-color: #ccc;}/* 变绿色 */.green {background-color: green;}/* 加边框 */.add-border {border: 1px solid #000;}div {min-height: 5em;max-width: 10em;}
html 源码
<div></div>
方法
element.classList.add()
添加一个类名
// 获取divlet div = document.querySelector("div");// 给div添加样式// 添加边框div.classList.add("add-border");//添加紫色div.classList.add("rebeccapurple");//添加灰色div.classList.add("gray");//添加绿色div.classList.add("green");
结果

element.classList.remove()
删除一个类名
// 获取divlet div = document.querySelector("div");//删除样式// 删除边框div.classList.remove("add-border");//删除绿色div.classList.remove("green");//删除灰色div.classList.remove("gray");
结果

element.classList.replace(old , new)
替换一个类名
// 获取divlet div = document.querySelector("div");// 替换样式// 把紫色替换成灰色div.classList.replace("rebeccapurple", "gray");
结果

element.classList.contains()
判断一个类型是不是存在,返回 true 和 false
// 获取divlet div = document.querySelector("div");// 判断一个类名是否存在// 判断元素是否含有rebeccapurplelet ret = div.classList.contains("rebeccapurple");console.log(ret); //falselet ret1 = div.classList.contains("gray");console.log(ret1); //true
结果

element.classList.toggle()
自动切换,有这个类就去掉, 没有就加上
<div></div><button>切换样式</button>
// 获取bottonlet btn = document.querySelector("button");// 获取divlet div = document.querySelector("div");// 监听点击事件btn.addEventListener("click", clk, false);// 切换,有这个类就去掉, 没有就加上function clk(e) {// 切换,有这个类就去掉, 没有就加上div.classList.toggle("rebeccapurple");}
结果

data-:为前缀的属性,称为数据属性。可以使用 dataset 对象来获取,获取时请省略掉”data-“。
例如
html 源码
<divclass="user"id="user-div"data-id="10"data-user-name="xiaoming"data-email="xiaoming@qq.com"data-tell="13866668888"></div>
js 源码
// dataset对象// 获取目标divlet div = document.getElementById("user-div");//console.log(div);// 获取id属性的值let id = div.dataset.id;console.log(id); //10// 将使用连接线命名的多个单词的属性名,转换"驼峰命名法"来获取//获取用户名let userName = div.dataset.userName;console.log(userName); //xiaoming// 获取邮箱let email = div.dataset.email;console.log(email); //xiaoming@qq.com//获取电话号码let tell = div.dataset.tell;console.log(tell); //13866668888
结果

注意:将使用连接线命名的多个单词的属性名,转换”驼峰命名法”来获取
js 的一些基础知识就介绍到这里了,基础的东西要学的扎实以后用起来得心应手。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号