可选链 ?.
1.为什么需要可选链?
当我们之前访问一个不存在的属性,会报错error
let user = {}; // 一个没有 "address" 属性的 user 对象
alert(user.address.street); // Error!
2.可选链
如果可选链 ?. 前面的部分是undefined 或者 null ,他会停止运算并返回该部分,也就是,返回undefined 或 null。
用法:value ?.prop
有了可选链,就可以对一个为null或者undefined属性安全引用:
let dataList = res?.data?.list
前提
可选链的使用前提是 ?. 前的变量必须已声明,如果没有就会出发错误
如果未声明变量user,那么user?.anything 会触发一个错误:
// ReferenceError: user is not defined
user?.address;
JS中 !! 的用法
var o={flag:true}; var test=!!o.flag;//等效于var test=o.flag||false; alert(test);
由于对null与undefined用!操作符时都会产生true的结果,
所以用两个感叹号的作用就在于,
如果明确设置了o中flag的值(非 null/undefined/0""/等值),自然test就会取跟o.flag一样的值;
如果没有设置,test就会默认为false,而不是 null或undefined。
数组方法
slice(截取)
slice():返回从原数组中指定开始下标到结束下标之间的项组成的新数组。slice()方法可以接受一或两个参数,即要返回项的起始和结束位置。在只有一个参数的情况下, slice()方法返回从该参数指定位置开始到当前数组末尾的所有项。如果有两个参数,该方法返回起始和结束位置之间的项——但不包括结束位置的项。
splice(数组更新)
splice():很强大的数组方法,它有很多种用法,可以实现删除、插入和替换。
-
1-添加元素:(三个元素)
- 第一个参数表示从那个下标位置开始添加,第二个参数为0,第三个参数表示要添加的元素,可以存在多个
-
2-替换元素:(三个元素)
- 第一个参数表示从那个下标位置开始添加(包含下标开始的位置),第二个参数表示替换的长度,第三个参数表示用什么元素替换
-
3-删除元素 (两个元素)
- 第一个参数为开始删除的下标位置,第二个参数为删除的长度,第三个参数不填写
sort(排序)
sort()
方法不传参数
默认是对数组的元素作为字符串进行升序排序。
- 数组元素是字母字符串时,正常按升序排列
const arr = ["Banana", "Orange", "Apple", "Mango"]
arr.sort()
console.log(arr) //输出结果 ["Apple", "Banana", "Mango", "Orange"]
var arr = [123,203,23,13,34,65,65,45,89,13,1];
function func(a,b){ return a-b; }
console.log(arr.sort(func)); //(11) [1, 13, 13, 23, 34, 45, 65, 65, 89, 123, 203]
- 数组元素是数字排序时,比如 3 会大于 12,因为 3 大于 1
const arr1 = ['3', '12', '23', '6']
const arr2 = [3, 12, 23, 6]
arr1.sort()
arr2.sort()
console.log(arr1)
console.log(arr2)
/*输出结果 ['12', '23', '3', '6'] [12, 23, 3, 6]
明显是错误的排序,可以传入比较函数来定义排序顺序
sort()
方法传入比较函数
const arr = [3, 12, 23, 6]
arr.sort(fn1)
console.log(arr)
arr.sort(fn2)
console.log(arr)
function fn1(a, b) {
return a-b // 升序
}
function fn2(a, b) {
return b-a // 降序
}
/*输出结果 [3, 6, 12, 23] [23, 12, 6, 3]
filter(过滤)
filter()创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。
1、filter() 不会对空数组进行检测;
2、filter() 不会改变原始数组。
使用实例
const array = [14, 17, 18, 32, 33, 16, 40];
const newArr = array.filter(num => num > 14)
console.log(newArr);//打印 [17,18,32,33,16,40]
const arr1 = {
location:[2,4,5],
};
[arr1.id1, arr1.id2, arr1.id3] = arr1.location.filter((item) => item),
const arr2 = {
id1:2,
id2:4,
id3:5,
};
arr2.location = [arr2.id1, arr2.id2, arr2.id3].filter((item) => item)
includes(是否包含)
includes 可以判断一个数组中是否包含某一个元素,并返回true 或者false
varstr = [2, 3, 4]; varn = str.includes(2); // result: true
includes可以包含两个参数,第二个参数表示判断的起始位置 起始位置第一个数字是0
- 用于多重条件判断优化
if(condtion === "justin1go" || condition === "justin2go" || condition === "justin3go"){
// some logic
}
如上,当我们对同一个值需要对比不同值的时候,我们完全可以使用如下的编码方式简化写法并降低耦合性:
const someConditions = ["justin1go", "justin2go", "justin3go"];
if(someConditions.includes(condition)) {
// some logic
}
- 字符串中使用include方法
var str = "I love JavaScript.";
var word = str.includes("javaScript"); // result: true
字符串方法
includes(是否包含)
includes() 方法用于判断字符串是否包含指定的子字符串。
语法:string.includes(searchvalue, start)
- searchvalue 必需值,要查找的字符串。
- start 可选值,设置从那个位置开始查找,默认为 0。
slice(截取)
slice(start, end) 方法可提取字符串的某个部分,并以新的字符串返回被提取的部分。
语法:string.slice(start,end)
- start 必须。 要抽取的片断的起始下标,第一个字符位置为 0。如果为负数,则从尾部开始截取。
- end 可选。 紧接着要截取的片段结尾的下标。若未指定此参数,则要提取的子串包括 start 到原字符串结尾的字符串。如果该参数是负数,那么它规定的是从字符串的尾部开始算起的位置。slice(-2) 表示提取原数组中的倒数第二个元素到最后一个元素(包含最后一个元素)。
split (分割)
split() 方法用于把一个字符串分割成字符串数组。
语法:string.split(separator,limit)
- separator 可选。字符串或正则表达式,从该参数指定的地方分割 string Object。
- limit 可选。该参数可指定返回的数组的最大长度。如果设置了该参数,返回的子串不会多于这个参数指定的数组。如果没有设置该参数,整个字符串都会被分割,不考虑它的长度。
concat(连接字符串)
concat() 方法用于连接两个或多个字符串。
该方法没有改变原有字符串,但是会返回连接两个或多个字符串新字符串
语法:string.concat(string1, string2, …, stringX)
- string1, string2, …, stringX 必需值。将被连接为一个字符串的一个或多个字符串对象。
JavaScript Map 对象
JavaScript 的对象(Object),本质上是键值对的集合(Hash 结构),但是传统上只能用字符串当作键。
ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。****
创建 Map 对象
创建一个对象为key值的Map对象
// 创建对象
const apples = {name: 'Apples'};
const bananas = {name: 'Bananas'};
const oranges = {name: 'Oranges'};
// 创建新的 Map
const fruits = new Map();
fruits.set(apples, 500);
fruits.set(bananas, 300);
fruits.set(oranges, 200);
key值为apples对象
以下方式新建Map对象的结果是一样的
// 创建对象
const apples = {name: 'Apples'};
const bananas = {name: 'Bananas'};
const oranges = {name: 'Oranges'};
// 创建新的 Map
const fruits = new Map([
[apples, 500],
[bananas, 300],
[oranges, 200]
]);
实例的属性和操作方法
1.size 属性
size属性返回 Map 结构的成员总数。
const map = new Map();
map.set('foo', true);
map.set('bar', false);
map.size // 2
2.set方法
set方法设置键名key对应的键值为value,然后返回整个 Map 结构。如果key已经有值,则键值会被更新,否则就新生成该键。
const m = new Map();
m.set('edition', 6) // 键是字符串
m.set(262, 'standard') // 键是数值
m.set(undefined, 'nah') // 键是 undefined
set方法返回的是当前的Map对象,因此可以采用链式写法。
let map = new Map()
.set(1, 'a')
.set(2, 'b')
.set(3, 'c');
3.get方法
get方法读取key对应的键值,如果找不到key,返回undefined。
const m = new Map();
const hello = function() { console.log('hello'); };
m.set(hello, 'Hello ES6!') //键是函数
m.get(hello) // Hello ES6!
4.has方法
has方法返回一个布尔值,表示某个键是否在当前 Map 对象之中。
const m = new Map();
m.set('edition', 6);
m.set(262, 'standard');
m.has('edition') //true
m.has('hello') //false
m.has(262) //true
5.delete方法
delete方法删除某个键,返回true。如果删除失败,返回false。
const m = new Map();
m.set('edition', 6);
m.has('edition') //true
m.delete('edition')
m.has('edition') //false
6.clear方法
clear方法清除所有成员,没有返回值。
const m = new Map();
m.set('edition', 6);
m.set(262, 'standard');
m.size //2
m.clear()
m.size //0
7.遍历方法
Map 结构原生提供三个遍历器生成函数和一个遍历方法。
- Map.prototype.keys():返回键名的遍历器。
- Map.prototype.values():返回键值的遍历器。
- Map.prototype.entries():返回所有成员的遍历器。
- Map.prototype.forEach():遍历 Map 的所有成员。
// 创建对象
const m = new Map([ ['name', 'zhangSan'], ['title', 'nihao'] ]);
m.keys()
m.values()
m.entries()
m.forEach((key, value) =>{ console.log(key, value)})
ES6 模块化
模块化的好处
模块化的优势有以下几点
- 防止命名冲突
- 代码复用
- 高维护性
ES6 模块化语法
模块功能主要由两个命令构成
- export 命令用于规定模块的对外接
- import 命令用于输入其他模块提供的功能
// m1.js
expert let school = '尚硅谷';
expert function teach() { console.log("我们可以教给你开发技能");}
<script type="module">
import * as m1 from "./src/js/m1.js";
console.log(m1)
</script>
模块导出数据语法
1、分别暴露(常用)
export let school = '尚硅谷';
export function teach() { console.log("我们可以教给你开发技能");}
2、统一暴露
let school = '尚硅谷';
function findJob(){ console.log("我们可以帮助你找工作!!"); }
export {school, findJob}
3、默认暴露
export default {
school: 'ATGUIGU',
change: function(){
console.log("我们可以改变你!!");
}
}
模块导入数据语法
1、通用导入方式
import * as m1 from './js/m1.js';
import * as m2 from './js/m2.js';
import * as m3 from './js/m3.js';
m3.default.change()
2、解构赋值导入
import {school, teach} from "./src/js/m1.js";
import {school as guigu, findJob} from "./src/js/m2.js";
import {default as m3} from "./src/js/m3.js";
3、简便方式导入,只能用于默认暴露
import m3 from "./src/js/m3.js";