JavaScript基础知识总结
目录
一、js代码位置
二、变量与数据类型
1、声明变量
2、基本类型(7种基本类型)
1、undefined和null
2、String ⭐
模板字符串(Template strings)
3、number和bigint ⭐
4、boolean ⭐
5、symbol
3、对象类型
1、Function ⭐⭐
1、默认参数
2、匿名函数
3、箭头函数
4、函数是对象
5、函数作用域
6、闭包
7、let、var与作用域
2、Array ⭐
1、push、shift、unshift、splice
2、join
3、map、filter、forEach
高阶函数:map,filter,forEach
回调函数: 例如作为参数传入的函数
4、split
5、升序,降序,洗牌
6、.find()
7、去重
8、数组和 (解构)
9、差集、交集、并集
3、Object ⭐⭐
属性
方法
get、set
1、语法
2、特殊:属性增删
3、用动object.defineProperty()对象态添加 get,set
4、特殊:this (this的三种情况,一种特例)
5、特殊:原型继承(对象之间)
6、特色:基于函数的原型继承
函数职责
4、JSON
1、 json对象 与 js对象 的区别在哪儿呢???
2、json 字符串与js对象的转换
3、JSON语法
5、动态类型
三、运算符与表达式 ⭐
1、 ===(严格相等)
2、||(逻辑或)
3、?? 与 ?.
4、...
5、[]{}
四、控制语句
1、for in
2、for of
3、try catch
五、Fetch API
一、js代码位置
-
放在script标签之间
<script>// js 代码 </script>
-
引入js脚本
<script src="js脚本路径"></script>
-
注意,到了框架之后,引入方式会有不同
-
二、变量与数据类型
1、声明变量
-
let ⭐
let 变量名 = 值;
-
let 声明的变量可以被多次赋值
let a = 100; // 初始值是100 a = 200; // ok,被重新赋值为200
-
-
const ⭐
const 常量 = 值;
-
const 修饰的叫常量,只能赋值一次
const b = 300; //初始值是300 b = 400; //error,不能再赋值
-
const 并不意味着它引用的内容不可修改,例如
const c = [1,2,3]; c[2] = 4; //ok,数组内容被修改成[1,2,4] c = [5,6]; // error.不能再次赋值
-
-
var
var声明的变量可以被多次赋值,例如
let a = 100; // 初始值是100 a = 200; // ok,被重新赋值为200
2、基本类型(7种基本类型)
1、undefined和null
-
执行表达式或函数,没有返回结果,出现undefined
-
访问数组不存在的元素,访问对象不存在的属性,出现undefined
-
定义变量,没有初始化,出现undefined
二者共同点
-
都没有属性、方法
-
Nullish(undefined和null共同的称呼)
二者区别
-
undefined 由 js 产生
-
null 有程序员提供
-
2、String ⭐
html 代码如下,用java和js种的字符串如何表示?
<a href="1.html">超链接</a>
java
String s1 = "<a href=\"1.html\">超链接</a>"; String s2 = """<a href="1.html">超链接</a> """;
js
let s1 = '<a href="1.html">超链接</a>'; let s2 = `<a href="1.html">超链接</a>`;
-
模板字符串(Template strings)
需求:拼接URI的请求参数,如
/test?name=zhang&age=18 /test?name=li&age=20
传统方法拼接:可读性低
let name = ; //zhang li ... let age = ; // 18 20 ... let uri = "/test?name" + name + "&age=" + age;
模板字符串方式:可读性高
let name = ; //zhang li ... let age = ; // 18 20 ... // 模板字符串方式 需要使用反引号使用 let uri = `/test?name=${name}&age=${age}`
3、number和bigint ⭐
-
number 类型表示的是双精度浮动小数,例如
10 / 3; //结果 3.3333333333333335
既然是浮点小数,那么可以除零
10 / 0; // 结果 Infinity 正无穷大 -10 / 0; // 结果 -Infinity 负无穷大
浮点小数都有运算精度问题,例如
2.0 - 1.1 // 结果 0.899999999999999
-
字符串转数字
parseInt("10"); // 结果是数字 10 parseInt("10.5"); // 结果是数字 10,去除了小数部分 parseInt("10") / 3; // 结果仍是为 number 浮点数,因此结果为 3.3333333333333335 parseInt("abc"); // 转换失败,结果是特殊值 NaN (Not a Number) -
需要表示真正的整数,需要用 bigint,数字的结尾用 n 表示它是一个 bigint 类型
10n / 3n; // 结果 3n,按整数除法处理
4、boolean ⭐
-
Truthy
-
Falsy
在js种,并不是 boolean 才能用于条件判断,你可以在if语句种使用【数字】、【字符串】...自拍为判断条件
let b = 1;
if(b){ // trueconsole.log("进入了");
}
这时就有一个规则,当需要条件判断时,这个值被当作 true 还是 false,当作 true 的值归类为 truthy,当作 false的值归类为 falsy
-
falsy
-
false
-
Nullish(null,undefined)
-
0 或 0n 或 NaN(0和 非数字)
-
"" 或 '' 或 `` (长度为零的空字符串)
-
5、symbol
3、对象类型
1、Function ⭐⭐
定义
function 函数名(参数){// 函数体return 结果; // 不是必须的
}
例子
function add(a,b){return a + b;
}
调用函数
函数名(实参);
例子
add(1,2); // 返回 3
add('a','b'); // 返回 ad
add(4,5,6); // 返回 9,第三个参数没有被用到,不会报错
add(1); // 返回 NaN,这是 b 没有定义是 undefined,undefined做数学运算结果就是 NaN
1、默认参数
java中(spring)要实现默认参数的效果
@RestController
public class MyController {@RequestMapping("/page")@ResponseBodypublic void page(@RequestParam(defaultValue="1") int page,@RequestParam(defaultValue="10") int siza){// ...}
}
js
function pagination(page = 1,size = 10){console.log(page,size)
}
// 显示默认值
pagination() // 1 10
// page 显示默认值
pagination(undefined,20) // 1 20
// size 显示默认值
pagination(2) // 2 10
2、匿名函数
语法
(function(参数){// 函数体return 结果;
})
例
(function(a,b){return a + b;
})
第一种场景:定义完毕后立刻调用
(function(a,b){return a + b;
})(1,2)
第二种场景:作为其它对象的方法,例如
页面有元素
<p id = "p1">点我啊</p>
此元素有一个onclick方法,会在鼠标单击这个元素后被执行,onclick方法刚开始是null,需要赋值后才能使用
document.getElementById("p1").onclick = (function(){console.log("鼠标单机了...")
});
3、箭头函数
(参数) => {// 函数体return 结果;
}
-
如果没有参数,()还是要保留
-
如果只有一个参数,()可以省略
-
如果函数体内只有一行代码,{}可以省略
-
如果函数体内的一行代码是返回代码,那么return也可以省略
例:
document.getElementById("p1").onclick = () => console.log("鼠标单机了...箭头函数")function abc(){console.log("bb"); } document.getElementById("p1").onclick = abc;
4、函数是对象
以下形式在 js 中非常常见!
-
可以参与赋值,例,具名函数也能参与赋值
function abc(){console.log("bb"); } document.getElementById("p1").onclick = abc; // 如果console.log(abc) 看不到对象的内部结构 // 就是用console.dir() 查看对象的内部结构 console.dir(abc) -
有属性、有方法
f abc()arguments: nullcaller: nulllength: 0name: "abc"➡prototype: {constructor: f}[[FunctionLocation]]: VM1962:1➡[[Prototype]]: f()➡[[Scopes]]: Scopes[1]-
其中带有 f 标记的是方法,不带的是属性
-
带有➡符号的可以继续展开,限于篇幅省略了
-
带有 [[ ]] 的是内置属性,不能访问,只能查看
-
相对重要的是 [[Prototype]] 和 [[Scopes]] 会在后面继承和作用域时讲到
-
-
可以作为方法参数
function a(){console.log('a'); } // 接受了函数作为参数的函数叫做 "高阶函数" function b(fn){ //fn 将来可以是一个函数对象console.log('b');fn(); // 调用函数对象 } // 将来调用b的时候可以把a传进去 b(a) -
可以作为方法返回值
// c函数把b函数当成了自己的返回值,那么c函数就是高阶函数 function c(){console.log("c");function d(){console.log("d");}return d; } c(); // 返回结果 c f d(){ console.log("d"); } c()(); // 返回函数对象 c d
5、函数作用域
函数可以嵌套( js 代码中很常见,只是嵌套的形式更多是匿名函数,箭头函数)
function a(){function b(){}
}
看下面的例子
function c(){var z = 30;
}
var x = 10;
function a(){var y = 20;function b(){// 看这里console.log(x,y);}b();
}
a();
-
以函数为分界线划定作用域,所有函数之外是全局作用域
-
查找变量时,由内向外查找
-
在内层作用域找到变量,就会停止查找,不会再找外层
-
所用作用域都找不到变量,报错
-
-
作用域本质上时函数对象的属性,可以通过 console.dir 来查看调式
6、闭包
var x = 10;
function a(){var y = 20;function b(){console.log(x,y);}return b;
}
a()(); // 在外面执行了 b
-
函数定义时,他的作用域已经确定好了,因此无论函数将来去了哪,都能从它的作用域中找到当时哪些变量
-
别被概念忽悠了,闭包就是指函数能够访问自己的作用域中变量
7、let、var与作用域
-
如果函数外层引用的是let变量,那么外层普通的{}也会作为作用域边界,最外层的let 也占一个 script 作用域
let x = 10; if(true){let y = 20;function b(){console.log(x,y);}console.dir(b); } // 3个作用域(不包含自己):1、if() 2、let x = 10 3、Global -
如果函数外层引用的是 var 变量,外层普通的 {} 不会被视为边界
var x = 10; if(true){var y = 20;function b(){console.log(x,y)}console.dir(b); } // 1个作用域(不包含自己) 1、Global -
如果 var 变量出现了重名,则他俩会被视为同一作用域中的同一个变量
var e = 10; if(true){var e = 20;console.log(e); // 打印 20 } console.log(e); // 因为是同一个变量,还是打印 20 -
如果是let,则视为两个作用域中的两个变量
let e = 10; if(true){let e = 20;console.log(e); // 打印 20 } console.log(e); // 打印10 -
要想里面的 e 和外面的 e 能区分开来,最简单的办法时改成let,或者用函数来界定作用域范围
var e = 10; if(true){function b(){var e = 20;console.log(e); } } console.log(e);
2、Array ⭐
语法
// 创建数组
let arr = [1,2,3];
// 获取数组元素
console.log(arr[0]); // 输出 1
// 修改数组元素
arr[0] = 5; // 数组元素变成了 [5,2,3]
// 遍历数组元素,其中 length 是数组属性, 代表数组长度
for(let i = 0; i < arr.length; i++){console.log(arr[i])
}
API
1、push、shift、unshift、splice
let arr = [1,2,3] arr.push(4); // 向数组尾部(右侧)添加元素,结果 [1,2,3,4] arr.shift(); // 从数组头部(左侧)移除元素,结果 [2,3,4] arr.splice(1,1) // 删除【参数1】索引位置的【参数2】个元素,结果[2,4] arr.splice(1,0,1) // 在【参数1】索引位置的添加【参数3】元素并且【参数3】的索引为【参数1】// 结果[2,1,4] 【参数2】的意思是删除的意思0是删除0个元素 arr.unshift(100) // 向数组头部(左侧)添加元素,结果[100,2,4] arr.slice(start,end)// slice()通过索引位置获取新的数组,该方法不会修改原数组,只是返回一个新的子数组。 左闭右开 [start,end)// 【参数1】:start - 必填,设定新数组的起始位置;如果是负数,则表示从数组尾部开始算起(-1指最后一个元素,-2 指倒数第二个元素,以此类推)。// 【参数2】end - 可选;设定新数组的结束位置;如果不填写该参数,默认到数组结尾;如果是负数,则表示从数组尾部开始算起(-1 指最后一个元素,-2指倒数第 二个元素,以此类推)。 Array.splice(start,delete_count,value,...) // 插入、删除、替换数组 // (1) start:开始插入和(或)删除的数组元素的下标。 // (2) delete_count:结束截取的数组下标,如果end是负数,表明从数组尾部开始计算. // (3)要插入数组的元素。value,-..: // 返回:如果从数组中删除了元素,则返回的是被删除的元素的数组
2、join
let arr = ['a','b','c'];
arr.join(); // 默认使用【,】作为连接符,结果'a,b,c'
arr.join(''); // 结果 'abc'
arr.join('-'); // 结果 'a-b-c'
3、map、filter、forEach
map 例子
let arr = [1,2,3,6];
// [10,20,30,60]
function a(i){ // 代表的新旧元素之间的变化规则return i * 10;
}
arr.map(a); // 具名函数,结果 [10,20,30,60]
// ↓ 进一步简化
arr.map( (i)=>{return i * 10}); // 箭头函数
// ↓ 进一步简化
arr.map( i => i * 10); // 箭头函数
-
传给 map 的函数,参数代表旧元素,返回值代表新元素,map的内部实现(伪代码)
function map(a){ // 参数是一个函数let narr = [];for(let i = 0; i < arr.length; i++){let o = arr[i]; // 旧元素let n = a(o); // 新元素narr.push(n);}return narr; }
filter 例子
let arr = [1,2,3,6]; arr.filter( i => i % 2 == 1); // 结果 [1,3]
-
传给 filter 的函数,参数代表旧元素,返回值 true 表示要留下的元素
forEach例子
let arr = [1,2,3,6];
for(let i = 0; i < arr.length; i++){console.log(arr[i])
}
arr.forEach( i => console.log(i));
arr.forEach((v,i) => {console.log(`n[${i}]=${v}`)})
-
高阶函数:map,filter,forEach
-
回调函数: 例如作为参数传入的函数
4、split
字符串转数组
let arr4 = '中国人'.split('')
console.log(arr4) // 输出结果 ['中','国','人']
5、升序,降序,洗牌
注意:num是一个非空数字数组
-
升序:num.sort((a,b) => a-b)
-
降序:num.sort((a,b) => b-a)
-
洗牌:num.sort(() => Math.random() > .5 ? a : b)
6、.find()
根据元素查找元素
let n = [1,2,3,4,5,6,7,8,9,10,2,4,2,1] console.log(n.find(e => e === 10)) // 10
7、去重
// 去重
console.log('-------------去重')
let nn = [1,2,3,4,5,6,5,7,5,8,6,9,4,6]
console.log(nn)
// 方法1 过滤
let arr = nn.filter((v,i)=>nn.indexOf(v)===i)
console.log(arr)
// 方法2 set方法
let arr2 = [...new Set(nn)]
console.log(arr2)
8、数组和 (解构)
let nn = [1,2,3,4,5,6,5,7,5,8,6,9,4,6]
let n2 = [1,2,3,4]
console.log(nn)
console.log(n2)
console.log('-------------数组和')
nn.push(...n2)
console.log(nn)
9、差集、交集、并集
let a1 = [1, 2, 3] let a2 = [11, 22, 33, 1, 2, 3] // 差集 let a4 = a2.filter(e => !a1.includes(e)) console.log(a4) // 交集 let a3 = a1.filter(e => a2.includes(e)) console.log(a3) // 并和 去重 a1.push(...a2.filter(e => !a1.includes(e))) console.log(a1)
3、Object ⭐⭐
-
属性
-
方法
-
get、set
1、语法
let obj = {属性名: 值,方法名: 函数,get 属性名() {},set 属性名(新值) {}
}
例1 写法1
let stu1 = {name: "小明",age: 18,study: function(){console.log(this.name + "爱学习");}
}
例2 写法2
let name = "小黑";
let age = 20;
let study = function(){console.log(this.name + "爱学习");
}
let stu2 = {name,age,study
}
例3 (例1的简写方式 重点)⭐
let stu3 = {name: "小明",age: 18,study(){console.log(this.name + "爱学习");}
}
-
注意:对象方法这么写,仅限于对象内部
例4
let stu4 = {_name: null, // 类似于java中私有成员变量get name(){console.log("进入了get");return this._name;},set name(name){console.log("进入了set");this._name = name;}
}
调用 get,set
stu4.name = "小白"; // 调用set 赋值语句 console.log(stu4.name) // 调用get
2、特殊:属性增删
对比以下 Java 中的 Object
-
Java 的 Object 是以类作为模板来创建,对象不能脱离类模板的范围,一个对象的属性,能用的方法都是确定好的
-
js 的对象,不需要什么模板,它的属性和方法可以随时加减
let stu = {name: '张三'}; stu.age = 18; // 这个age属性是创建stu后加上的 delete stu.age; // 删除 stu这个对象中的age属性 stu.study = function() {console.log(this.name + "在学习"); // 这个study方法是后加的 }
3、用动object.defineProperty()对象态添加 get,set
let stu = {_name:null
};
// 第一个参数 给哪一个对象定义属性
// 第二个参数 属性名 不要和_name冲突
// 第三个参数 包含了get,set的定义
object.defineProperty(stu,"name",{get(){return this._name},set(name){this._name = name;}
});
4、特殊:this (this的三种情况,一种特例)
先来对 Java 中的 this 有个理解
public class TestMethod{static class Student{private String name;public Student(String name){this.name = name;}// 隐式参数Student thispublic void study(Student this,String subject){System.out.println(this.name + ": 在学习" + subject);}}public static void main(String[] args){Student stu = new Student("小明");// 下面的代码,本质上是执行 study(stu, "java"),因此 this 就是 stustu.study("java");}}
js 中的 this 也是隐式参数,但是它与函数运行时上下文相关
①、一个”落单“的函数
function study(subject){console.log(this.name + "在学习" + subject); }测试以下
study("js"); // 输出 在学习 js
这是因为此时函数执行,全局对象 window 被当作了 this, window 对象的 name 属性是空串
②、同样的函数,如果作为对象的方法
let stu = {name: "小白",study
}
这种情况下,会将当前对象作为 this
③、.call 还可以动态改变this
let stu = {name:"小黑"};
// 第一个参数:你要把this视为谁?
// 第二个参数:传入study方法需要的形参
study.call(stu,"js"); // 输出 小黑在学习 js
这回 study 执行时,就把 call 的第一个参数 stu 作为 this
例外:在箭头函数内出现的 this,以外层 this 理解
用匿名函数
let stu = {name: "小花",friends: ["小白","小黑","小明"],play:function(){ // play:function() == play()this.friends.forEach(function(e){console.log(this.name + "与" + e + "在玩耍");});}
}
stu.play();
// 第一个this指的时stu 第二个this指的是window(因为第二个函数时落单的函数)
-
this.name 所在的函数时【落单】的函数,因此 this 代表 window
输出结果为
与小白在玩耍 与小黑在玩耍 与小明在玩耍
用箭头函数
let stu = {name: "小花",friends: ["小白","小黑","小明"],play(){this.friends.forEach(e =>{console.log(this.name + "与" + e + "在玩耍");});}
}
//在箭头函数内出现的 this,以外层 this 理解
-
this.name 所在的函数是箭头函数,因此 this 要看它外层的 play 函数, play 又是属于 stu 的方法,因此 this 代表 stu 对象
输出结果为
小花与小白在玩耍 小花与小黑在玩耍 小花与小明在玩耍
不用箭头函数的做法
let stu = {name: "小花",friends: ["小白","小黑","小明"],play(){let me = this;this.friends.forEach(function(e){console.log(me.name + "与" + e + "在玩耍");});}
}
5、特殊:原型继承(对象之间)
let father = {f1: '父属性',m1: function(){console.log("父方法");}
}
// .create:以父对象为原型创建一个子对象
let son = Object.create(father);
console.log(son.f1); // 打印 父属性
son.m1 // 打印 父方法
-
father 是父对象,son 去调用 .m1 或 .f1 时,自身对象没有,就到父对象找
-
son 自己可以添加自己的属性和方法
-
son 里有特殊属性
__proto__代表它的父对象,js 术语:son 的原型对象 -
不同浏览器对打印 son 的
__proto__属性时显示不同-
Edge 打印 console.dir(son) 显示
[[prototype]] -
Firefox 打印 console.dir(son) 显示
<protorype>
-
6、特色:基于函数的原型继承
出于方便的原因,js 又提供了一种基于函数的原型继承
函数职责
负责创建子对象,给子对象提供属性,方法,功能上相当于构造方法
函数有个特殊的属性 prototype,它就是函数创建的子对象的父对象
注意! 名字有差异,这个属性的作用就是为新对象提供原型
function cons(f2){// 创建子对象(this),给子对象提供属性和方法this.f2 = f2,this.m2 = function (){console.log("子方法");}
}
// cons.prototype 就是父对象
cons.prototype.f1 = "父属性";
cons.prtotype.m1 = function(){console.log("父方法");
}
配合 new 关键字,创建子对象
let son = new cons("子属性");
子对象的__proto__就是函数的 prototype 属性
4、JSON
之前我们将 http 请求格式时,讲过 json 这种数据格式,他的语法看起来与 js 对象非常相似,例如:
一个 json 对象可以张这样:
{"name":"张三","age":18
}
一个 js 对象长这样
{name:"张三",age:18
}
1、 json对象 与 js对象 的区别在哪儿呢???
本质不同
json 对象本质上就是个字符串,它的职责是作为客户端和服务器之间传递数据的一种格式,它的属性只是样子货
js 对象是切切实实的对象,可以有属性方法
语法细节不同
json 中只能有null、true|false、数字、字符串(只有双引号)、对象、数组
json 中不能有除以上的其他 js 对象的特性、如方法等
json 中的属性必须用双引号引起来
2、json 字符串与js对象的转换
// 把 json 字符串转化为 js 对象 返回对象js对象 JSON.parse(json字符串); // 把 js 对象转换成 json 字符串 返回json字符串 JSON.stringify(js对象);
3、JSON语法
let json = `{"name":"张三","age":18
}`;
let obj = JSON.parse(json);
5、动态类型
静态类型语言,如 Java,值有类型,变量也有类型、赋值给变量时,类型要相符
int a = 10; String b = "abc"; int c = "abc"; // 错误
而 js 属于动态类型语言,值有类型,但变量没有类型,赋值给变量时,没要求
例如
let a = 200; let b = 100; b = 'abc'; b = true;
动态类型看起来比较灵活,但变量没有类型,会给后期维护带来困难,例如
function test(obj){// obj 的类型未知,必须根据不同类型做出各种容错处理
}
三、运算符与表达式 ⭐
+ - * / % **
+= -= *= /= %= **=
++ --
位移算、移位运算(估计大家用不着,用到时候上网搜索)
== != > >= < <=
=== !==⭐
&& || !⭐
?? ?.⭐
...⭐
解构赋值[]{}⭐
**:乘方
**=:乘方等
1、 ===(严格相等)
严格相等运算符,用作逻辑判等。
1 == 1 // 返回 true 1 == '1' // 返回 true,会先将右侧的字符串转为数字,再做比较 1 === '1' // 返回 false。类型不等,直接返回 false
补充:typeod 查看某个值的类型
typeof 1; // 返回 'number' typeof 'a'; // 返回 'string'
2、||(逻辑或)
需求,如果参数 n 没有传递,给它一个 【男】
推荐做法
function test(n = '男'){console.log(n);
}
你可能的做法
function test(n){if(n === undefined){n = '男';}console.log(n)
}
还可能时这样
function test(n){n = (n === undefined) ? '男' : n;console.log(n);
}
一些老旧代码中可能的做法(不推荐,有潜在问题)
function test(n){n = n || '男';console.log(n);
}
它的语法时
值1 || 值2
如果值1 时 Truthy,返回值1,如果值1 时 Falsy 返回值2
3、?? 与 ?.
?. 可选链操作符用于访问可能为空或未定义的属性或方法,它允许我们安全地访问嵌套对象的属性
?? 空值合并操作符用于检查一个变量是否为 null 或 undefined,如果是,则返回一个默认值,否则返回该变量的值。与传统的逻辑运算符 || 不同,?? 只会在左侧的值为 null 或 undefined 时返回右侧的默认值,对于其他假值(如空字符串、0、false 等)并不会返回默认值,而是会返回它本身。
需求,如果参数 n 没有传递值或是 null,给它一个【男】
如果用传统办法
function test(n){if(n === undefined || n === null){n = '男';}console.log(n);
}
用 ??
function test(n){n = n ?? '男';console.log(n)
}
需求,函数参数是一个对象,可能包含有子属性
例如,参数可能是
let stu1 = {name:"张三",address:{city:'北京'}
}
let stu2 = {name:"李四",
}
let stu3 = {name:"李四",address: null
}
现在要访问子属性
function test(stu){console.log(stu.address.city)
}
现在希望当某个属性是 nullish 时,短路并返回 undefined
function test(stu){console.log(stu.address?.city)
}
用传统办法
function test(stu){if(stu.address === undefined || stu.address === null){console.log(undefined);return;}console.log(stu.address.city);
}
4、...
展开运运算符
作用1:打散数组传递给多个参数
let arr = [1,2,3];
function test(a,b,c){console.log(a,b,c);
}
-
传统的打散写法
test(arr[0],arr[1],arr[2]); // 输出 1,2,3
-
展开运算符写法
test(...arr); // 输出 1,2,3
-
打散可以理解为【去掉了】数组外侧的中括号,只剩下数组元素
-
作用2:复制数组或对象
数组
let arr1 = [1,2,3]; let arr2 = [...arr1]; // 复制数组
对象
let obj1 = {name:'张三',age:18};
let obj2 = {...obj1}; // 复制对象
注意:展开运算符复制属于浅拷贝(只能复制一层,多层的话就是引用了),例如
let o1 = {name:'张三',address:{city:'北京'}}
let o2 = {...o1};
作用3:合并数组或对象
合并数组
let a1 = [1,2]; let a2 = [3,4]; let b1 = [...a1,...a2]; // 合并数组 [1,2,3,4] let b2 = [...a2,5,...a1] // 输出 [3,4,5,1,2]
合并对象
let o1 = {name:'张三'};
let o2 = {age:18};
let o3 = {name:'李四'};
let n1 = {...o1, ...o2}; // 结果 {name:'张三',age:18}
let n2 = {...o1, ...o2, ...o3}; // 结果 {name:'李四',age:18}
5、[]{}
解构赋值
[]
用在声明变量是
let arr = [1,2,3]; // 我们把中括号叫做数组的解构赋值 let [a,b,c] = arr // 结果 a=1,b=2,c=3
用在声明参数时
let arr = [1,2,3];
function test([a,b,c]){console.log(a,b,c);
}
test(arr); // 结果 a=1,b=2,c=3
{}
用在声明变量时
let obj = {name:"张三",age:18};
// 声明的变量名称要和obj的对象属性一致
let {name,age} = obj;
用在声明参数时
let obj = {name:"张三",age:18};
function test({name,age}){console.log(name,age);
}
test (obj);
四、控制语句
if ... else
switch
while
do ... while
for
for ... in⭐
for ... of⭐
try ... catch⭐
1、for in
主要用来遍历对象
let father = {name:'张三',age:18,study:function(){}};
for(const n in father){console.log(n);
}
// 结果 name age study
-
其中 const n 代表遍历出来的属性名
-
注意1:方法名也能被遍历出来(它其实也算一种特殊属性)
-
注意2:遍历子对象时,父对象的属性会跟着遍历出来
let son = object.create(father); son.sex = "男"; for(const n in son){console.log(n); } // 结果 sex name age study -
注意3:在 for in 内获取属性值,要使用 [] 语法,而不能用 . 语法
for(const n in son){console.log(n,son[n]); } // 结果 // sex 男 // name 张三 // age 18 // study f (){}
2、for of
主要用来遍历数组,也可以时其它可迭代对象,如Map,Set等
let a1 = [1,2,3];
for(const i of a1){console.log(i);
}
let a2 = [{name:'张三',age:18},{name:'李四',age:20},{name:'王五',age:22}
];
for(const obj of a2){console.log(obj.name,obj.age);
}
for(const {name,age} of a2){console.log(name,age);
}
3、try catch
let stu1 = {name:'张三',age:18,address:{city:'北京'}};
let stu2 = {name:'张三',age:18};
function test(stu){try{console.log(stu.address.city); } catch(e){console.log('出现了异常',e.message);}}
五、Fetch API
Fetch API 可以用来获取远程数据,他有两种方式接受结果,同步方式与异步方式
格式
fetch(url,options) // 返回 Promise对象
同步方式
// const 结果 = await fetch(url,options); const 结果 = await Promise; // 后续代码
-
await 关键字必须在一个标记了 async 的 function 内来使用
-
后续代码不会在结果返回前执行
异步方式
fetch(url,options).then(结果 => {...})
// 后续代码
-
后续代码不必等待结果返回就可以执行
相关文章:
JavaScript基础知识总结
目录 一、js代码位置 二、变量与数据类型 1、声明变量 2、基本类型(7种基本类型) 1、undefined和null 2、String ⭐ 模板字符串(Template strings) 3、number和bigint ⭐ 4、boolean ⭐ 5、symbol 3、对象类型 1、Fun…...
技术面试与HR面:两者之间的关联与区别
🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文…...
【Redis】为什么要学 Redis
文章目录 前言一、Redis 为什么快二、Redis 的特性2.1 将数据储存到内存中2.2 可编程性2.3 可扩展性2.4 持久性2.5 支持集群2.6 高可用性 三、Redis 的应用场景四、不能使用 Redis 的场景 前言 关于为什么要学 Redis 这个问题,一个字就可以回答,那就是&…...
动静态库生成使用
🔥🔥 欢迎来到小林的博客!! 🛰️博客主页:✈️林 子 🛰️博客专栏:✈️ Linux 🛰️社区 :✈️ 进步学堂 🛰…...
LLVM编译安装
LLVM编译安装 #全量下载 git clone https://github.com/llvm/llvm-project.git #只下载最新commit版本 git clone --depth 1 https://github.com/llvm/llvm-project.git#配置 #!/bin/bash set -ex cmake -S llvm -B build -DCMAKE_INSTALL_PREFIX/data0/huozai/software/insta…...
表的内连接和外连接
表的连接是SQL中的一种操作,用于将两个或多个表中的数据按照某个条件进行关联。 内连接 使用内连接将两个表(Table1 和 Table2)进行连接: select * from Table1 inner join Table2 on Table1.id Table2.id;举例: -- 用普通的写法 select…...
三、C#—变量,表达式,运算符(3)
🌻🌻 目录 一、变量1.1 变量1.2 使用变量的步骤1.3 变量的声明1.4 变量的命名规则1.5 变量的初始化1.6 变量初始化的三种方法1.7 变量的作用域1.8 变量使用实例1.9 变量常见错误 二、C#数据类型2.1 数据类型2.2 值类型2.2.1 值类型直接存储值2.2.2 简单类…...
纷享销客受邀出席CDIE2023数字化创新博览会 助力大中型企业增长
2023年,穿越周期,用数字化的力量重塑企业经营与增长的逻辑,再次成为企业数字化技术应用思考的主旋律,以数字经济为主线,数字技术融入产业发展与企业增长为依据,推动中国企业数字化升级。 9月5日,…...
linux下qt交叉编译 tslib 库
在 Linux 下进行 Qt 的交叉编译,并包含 tslib 库,可以按照以下步骤进行操作:1. 准备交叉编译工具链:首先,你需要准备适用于目标平台的交叉编译工具链。这个工具链包括交叉编译器、 2. 链接器和其他相关的工具ÿ…...
2.13 PE结构:实现PE代码段加密
代码加密功能的实现原理,首先通过创建一个新的.hack区段,并对该区段进行初始化,接着我们向此区段内写入一段具有动态解密功能的ShellCode汇编指令集,并将程序入口地址修正为ShellCode地址位置处,当解密功能被运行后则可…...
Rust更换Cargo国内源,镜像了寂寞
换皮不换身 换了国内源,构建时该卡还会卡。因为它所谓的换源,只是更换crates.io“索引”的源,而不是package“内容”的源。换了国内源后,在国内编译时访问 crates.io-index 自然会快很多,可是crates.io-index里面的信…...
【网络安全带你练爬虫-100练】第23练:文件内容的删除+写入
目录 0x00 前言: 0x02 解决: 0x00 前言: 本篇博文可能会有一点点的超级呆 0x02 解决: 你是不是也会想: 使用pyrhon将指定文件夹位置里面的1.txt中数据全部删除以后---->然后再将参数req_text的值写入到1.txt …...
ESP32蓝牙实例-BLE服务器与客户端通信
BLE服务器与客户端通信 文章目录 BLE服务器与客户端通信1、软件准备2、硬件准备3、代码实现3.1 BLE服务器实现3.2 Android手机测试BLE服务器3.3 ESP32 BLE客户端在本文中,我们将介绍如何使用低功耗蓝牙在两个 ESP32 开发板之间执行 BLE 服务器客户端通信。 换句话说,将介绍如…...
第11章_瑞萨MCU零基础入门系列教程之SysTick
本教程基于韦东山百问网出的 DShanMCU-RA6M5开发板 进行编写,需要的同学可以在这里获取: https://item.taobao.com/item.htm?id728461040949 配套资料获取:https://renesas-docs.100ask.net 瑞萨MCU零基础入门系列教程汇总: ht…...
【面试题精讲】如何使用Stream的聚合功能
有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,认准https://blog.zysicyj.top 首发博客地址 系列文章地址 求和(Sum): List<Integer> numbers Arrays.asList(1, 2, 3, 4, 5);int sum n…...
Linux 中的 chmod 命令及示例
在 Unix 操作系统中,chmod命令用于更改文件的访问模式。该名称是change mode的缩写。其中规定每个文件和目录都有一组权限来控制权限,例如谁可以读取、写入或执行该文件。其中权限分为三类:同时读、写和执行,用“r”、“w”和“x”表示。这些字母组合在一起形成一组用户的特…...
sannaing i14 pro max使用体验
体验了一把山寨机,不明真相的人会以为这是三星的英文标志,又是pro又是max的,价格600,进系统去看了配置,cpu写的是snapdragon 888,运存12g,内存500g。下了个安兔兔也是被忽悠了,它也以…...
Shazam音乐检索算法原理及实现
算法基本流程如下: 1. 采集音乐库 2. 音乐指纹采集 3. 采用局部最大值作为特征点 4. 将临近的特征点进行组合形成特征点对 5. 对每个特征点对进行hash编码 编码过程:将f1和f2进行10bit量化,其余bit用来存储时间偏移合集形成32bit的hash码 …...
vue递归组件
父组件: <template><div><treeVue :treeData"treeData"></treeVue></div> </template><script setup lang"ts"> import { reactive } from "vue"; import treeVue from "./tree.vue…...
软件测试/测试开发丨测试用例自动录入 学习笔记
点此获取更多相关资料 本文为霍格沃兹测试开发学社学员学习笔记分享 原文链接:https://ceshiren.com/t/topic/27139 测试用例自动录入 测试用例自动录入的价值 省略人工同步的步骤,节省时间 兼容代码版本的自动化测试用例 用例的执行与调度统一化管理…...
使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...
什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
Java毕业设计:WML信息查询与后端信息发布系统开发
JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发,实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构,服务器端使用Java Servlet处理请求,数据库采用MySQL存储信息࿰…...
Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...
RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...
【C++】纯虚函数类外可以写实现吗?
1. 答案 先说答案,可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…...
【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...
Windows电脑能装鸿蒙吗_Windows电脑体验鸿蒙电脑操作系统教程
鸿蒙电脑版操作系统来了,很多小伙伴想体验鸿蒙电脑版操作系统,可惜,鸿蒙系统并不支持你正在使用的传统的电脑来安装。不过可以通过可以使用华为官方提供的虚拟机,来体验大家心心念念的鸿蒙系统啦!注意:虚拟…...
aardio 自动识别验证码输入
技术尝试 上周在发学习日志时有网友提议“在网页上识别验证码”,于是尝试整合图像识别与网页自动化技术,完成了这套模拟登录流程。核心思路是:截图验证码→OCR识别→自动填充表单→提交并验证结果。 代码在这里 import soImage; import we…...
