当前位置: 首页 > news >正文

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代码位置

  1. 放在script标签之间

    <script>// js 代码    
    </script>
  2. 引入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 中非常常见!

  1. 可以参与赋值,例,具名函数也能参与赋值

    function abc(){console.log("bb");
    }
    ​
    document.getElementById("p1").onclick = abc;
    ​
    // 如果console.log(abc) 看不到对象的内部结构
    // 就是用console.dir()  查看对象的内部结构
    console.dir(abc)

  2. 有属性、有方法

    f abc()arguments: nullcaller: nulllength: 0name: "abc"➡prototype: {constructor: f}[[FunctionLocation]]: VM1962:1➡[[Prototype]]: f()➡[[Scopes]]: Scopes[1]
    • 其中带有 f 标记的是方法,不带的是属性

    • 带有➡符号的可以继续展开,限于篇幅省略了

    • 带有 [[ ]] 的是内置属性,不能访问,只能查看

    • 相对重要的是 [[Prototype]] 和 [[Scopes]] 会在后面继承和作用域时讲到

  3. 可以作为方法参数

    function a(){console.log('a');
    }
    ​
    // 接受了函数作为参数的函数叫做 "高阶函数"
    function b(fn){         //fn 将来可以是一个函数对象console.log('b');fn();               // 调用函数对象
    }
    ​
    // 将来调用b的时候可以把a传进去
    b(a)

  4. 可以作为方法返回值

    // 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 又提供了一种基于函数的原型继承

函数职责
  1. 负责创建子对象,给子对象提供属性,方法,功能上相当于构造方法

  2. 函数有个特殊的属性 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对象 的区别在哪儿呢???
  1. 本质不同

  • json 对象本质上就是个字符串,它的职责是作为客户端和服务器之间传递数据的一种格式,它的属性只是样子货

  • js 对象是切切实实的对象,可以有属性方法

  1. 语法细节不同

  • 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、基本类型&#xff08;7种基本类型&#xff09; 1、undefined和null 2、String ⭐ 模板字符串&#xff08;Template strings&#xff09; 3、number和bigint ⭐ 4、boolean ⭐ 5、symbol 3、对象类型 1、Fun…...

技术面试与HR面:两者之间的关联与区别

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…...

【Redis】为什么要学 Redis

文章目录 前言一、Redis 为什么快二、Redis 的特性2.1 将数据储存到内存中2.2 可编程性2.3 可扩展性2.4 持久性2.5 支持集群2.6 高可用性 三、Redis 的应用场景四、不能使用 Redis 的场景 前言 关于为什么要学 Redis 这个问题&#xff0c;一个字就可以回答&#xff0c;那就是&…...

动静态库生成使用

&#x1f525;&#x1f525; 欢迎来到小林的博客&#xff01;&#xff01;       &#x1f6f0;️博客主页&#xff1a;✈️林 子       &#x1f6f0;️博客专栏&#xff1a;✈️ Linux       &#x1f6f0;️社区 :✈️ 进步学堂       &#x1f6f0…...

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中的一种操作&#xff0c;用于将两个或多个表中的数据按照某个条件进行关联。 内连接 使用内连接将两个表(Table1 和 Table2)进行连接&#xff1a; select * from Table1 inner join Table2 on Table1.id Table2.id;举例&#xff1a; -- 用普通的写法 select…...

三、C#—变量,表达式,运算符(3)

&#x1f33b;&#x1f33b; 目录 一、变量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年&#xff0c;穿越周期&#xff0c;用数字化的力量重塑企业经营与增长的逻辑&#xff0c;再次成为企业数字化技术应用思考的主旋律&#xff0c;以数字经济为主线&#xff0c;数字技术融入产业发展与企业增长为依据&#xff0c;推动中国企业数字化升级。 9月5日&#xff0c…...

linux下qt交叉编译 tslib 库

在 Linux 下进行 Qt 的交叉编译&#xff0c;并包含 tslib 库&#xff0c;可以按照以下步骤进行操作&#xff1a;1. 准备交叉编译工具链&#xff1a;首先&#xff0c;你需要准备适用于目标平台的交叉编译工具链。这个工具链包括交叉编译器、 2. 链接器和其他相关的工具&#xff…...

2.13 PE结构:实现PE代码段加密

代码加密功能的实现原理&#xff0c;首先通过创建一个新的.hack区段&#xff0c;并对该区段进行初始化&#xff0c;接着我们向此区段内写入一段具有动态解密功能的ShellCode汇编指令集&#xff0c;并将程序入口地址修正为ShellCode地址位置处&#xff0c;当解密功能被运行后则可…...

Rust更换Cargo国内源,镜像了寂寞

换皮不换身 换了国内源&#xff0c;构建时该卡还会卡。因为它所谓的换源&#xff0c;只是更换crates.io“索引”的源&#xff0c;而不是package“内容”的源。换了国内源后&#xff0c;在国内编译时访问 crates.io-index 自然会快很多&#xff0c;可是crates.io-index里面的信…...

【网络安全带你练爬虫-100练】第23练:文件内容的删除+写入

目录 0x00 前言&#xff1a; 0x02 解决&#xff1a; 0x00 前言&#xff1a; 本篇博文可能会有一点点的超级呆 0x02 解决&#xff1a; 你是不是也会想&#xff1a; 使用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开发板 进行编写&#xff0c;需要的同学可以在这里获取&#xff1a; https://item.taobao.com/item.htm?id728461040949 配套资料获取&#xff1a;https://renesas-docs.100ask.net 瑞萨MCU零基础入门系列教程汇总&#xff1a; ht…...

【面试题精讲】如何使用Stream的聚合功能

有的时候博客内容会有变动&#xff0c;首发博客是最新的&#xff0c;其他博客地址可能会未同步,认准https://blog.zysicyj.top 首发博客地址 系列文章地址 求和&#xff08;Sum&#xff09;&#xff1a; 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使用体验

体验了一把山寨机&#xff0c;不明真相的人会以为这是三星的英文标志&#xff0c;又是pro又是max的&#xff0c;价格600&#xff0c;进系统去看了配置&#xff0c;cpu写的是snapdragon 888&#xff0c;运存12g&#xff0c;内存500g。下了个安兔兔也是被忽悠了&#xff0c;它也以…...

Shazam音乐检索算法原理及实现

算法基本流程如下&#xff1a; 1. 采集音乐库 2. 音乐指纹采集 3. 采用局部最大值作为特征点 4. 将临近的特征点进行组合形成特征点对 5. 对每个特征点对进行hash编码 编码过程&#xff1a;将f1和f2进行10bit量化&#xff0c;其余bit用来存储时间偏移合集形成32bit的hash码 …...

vue递归组件

父组件&#xff1a; <template><div><treeVue :treeData"treeData"></treeVue></div> </template><script setup lang"ts"> import { reactive } from "vue"; import treeVue from "./tree.vue…...

软件测试/测试开发丨测试用例自动录入 学习笔记

点此获取更多相关资料 本文为霍格沃兹测试开发学社学员学习笔记分享 原文链接&#xff1a;https://ceshiren.com/t/topic/27139 测试用例自动录入 测试用例自动录入的价值 省略人工同步的步骤&#xff0c;节省时间 兼容代码版本的自动化测试用例 用例的执行与调度统一化管理…...

来学Python啦,大话字符串

To be a happy man&#xff0c; reading&#xff0c; travel&#xff0c; hard work&#xff0c; care for the body and mind。做一个幸福的人&#xff0c;读书&#xff0c;旅行&#xff0c;努力工作&#xff0c;关心身体和心境。 前面我们讲解过关于用Python写温度转换器&…...

pyqt5设置背景图片

PyQt5设置背景图片 1、打开QTDesigner 创建一个UI&#xff0c;camera.ui。 2、创建一个pictures.qrc文件 在ui文件同级目录下先创建一个pictures.txt&#xff0c;填写内容&#xff1a; <RCC><qresource prefix"media"><file>1.jpg</file>…...

C# WPF 自己写的一个模拟病毒传播的程序,有可视化

源代码: https://github.com/t39q/VirusSpread 主要代码 using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks;namespace VirusSpread.Bu…...

stable diffusion实践操作-大模型介绍-SDXL1大模型

系列文章目录 大家移步下面链接中&#xff0c;里面详细介绍了stable diffusion的原理&#xff0c;操作等&#xff08;本文只是下面系列文章的一个写作模板&#xff09;。 stable diffusion实践操作 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生…...

软考高级系统架构设计师系列案例考点专题四:嵌入式系统

软考高级系统架构设计师系列案例考点专题四:嵌入式系统 一、相关概念二、软件可靠性和硬件可靠性的区别三、可靠性指标四、可靠性设计五、冗余技术六、软件容错七、双机容错技术八、集群技术九、负载均衡十、可维护性的评价指标十一、软件维护的分类嵌入式每年必考一题,但是属…...

Django Form实现表单使用及应用场景

首先需要定义一个使用场景&#xff1a; 音乐网站的前端部分可以添加上传歌手的单曲&#xff0c; 这个添加页面就使用django form表单来实现。 目录 数据表内容 歌手表及表模型 单曲表及表模型 演示表单使用 设置路由 创建form.py 视图实例化表单类 模板使用表单对象 表…...

golang面试题:json包变量不加tag会怎么样?

问题 json包里使用的时候&#xff0c;结构体里的变量不加tag能不能正常转成json里的字段&#xff1f; 怎么答 如果变量首字母小写&#xff0c;则为private。无论如何不能转&#xff0c;因为取不到反射信息。如果变量首字母大写&#xff0c;则为public。 不加tag&#xff0c…...

国内项目管理中级证书CSPM-3正在报名!

CSPM-3中级项目管理专业人员认证&#xff0c;是中国标准化协会&#xff08;全国项目管理标准化技术委员会秘书处&#xff09;&#xff0c;面向社会开展项目管理专业人员能力的等级证书。旨在构建多层次从业人员培养培训体系&#xff0c;建立健全人才职业能力评价和激励机制的要…...

vue表格不显示列号123456

我在网上找了半天&#xff0c;都是如何添加列号123456的&#xff0c;没有找到不显示列号的参考&#xff0c;现在把这个解决了&#xff0c;特此记录一下。 没有加右边的就会显示&#xff0c;加上右边的就隐藏了...

【大数据】Kafka 入门指南

Kafka 入门指南 1.Kafka 简介2.Kafka 架构3.分区与副本4.偏移量5.消费者组6.总结 1.Kafka 简介 Apache Kafka 是一种高吞吐、分布式的流处理平台&#xff0c;由 LinkedIn 开发并于 2011 年开源。它具有 高伸缩性、高可靠性 和 低延迟 等特点&#xff0c;因此在大型数据处理场景…...

网店代运营的公司有哪些/百度搜索怎么优化

Fiksu是一家帮助移动开发者有效找寻新用户的公司&#xff0c;公司总部位于波士顿。该公司刚刚获得了新一轮由高通风险投资公司领投的1000万美元融资。 “对于我们来说&#xff0c;高通公司可以提供强大的战略帮助。”Fiksu公司业务发展副总裁Craig Palli说&#xff0c;“高通和…...

网站建设飠金手指下拉/成人本科

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼#include void sub_reverse(char *);int main(){char str[256] "The only way to learn a new programming language is by writing programs in it";char string[256] "Oh,My god!What are you doing here? \&q…...

常州模板网站建设咨询/成都最新热门事件

//js 库代码&#xff1a; //ZAJ.js库代码 (function (){ //注册命名空间 AZJ 到window对象上 window[AZJ] {} //getElementsByClassName包含两个参数&#xff1a;类名&#xff0c;标签名 function getEleme…...

网站栏目结构设计/使用最佳搜索引擎优化工具

python实用函数实现 分割列表: def TyChunk(l: list, size: int):return list(map(lambda x: l[x * size: x * size size],list(range(0, ceil(len(l) / size)))))扭转列表: def TyTranspose(array):return [list(i) for i in list(zip(*array))]...

德育工作网站建设方案/百度推广代理开户

试验网站#3搜索引擎优化收录情况记录日期Yahoogooglebaidusogou每日收录每日收录增量每日收录每日收录增量每日收录每日收录增量每日收录每日收录增量2007-7-7迁移至不限带宽的服务器&#xff0c;地理位置在美国2007-7-193650 1 6 0 2007-7-253703531141132216002007-7-263705…...

企业网站建设参考资料/连云港seo优化

资源介绍资源名称&#xff1a;MSSQL、MySQL、Oracle 三大主流数据库快速上手教程目录&#xff1a;MSSQL、MySQL、Oracle 三大主流数据库快速上手第一章MSSQL、MySQL、Oracle 三大主流数据库快速上手第七章1-4MSSQL、MySQL、Oracle 三大主流数据库快速上手第三章1-5MSSQL、MySQL…...