JS基础知识

102 阅读8分钟

可选链 ?.

1.为什么需要可选链?

当我们之前访问一个不存在的属性,会报错error
   let user = {}; // 一个没有 "address" 属性的 user 对象
   alert(user.address.street); // Error!

2.可选链

如果可选链 ?. 前面的部分是undefined 或者 null ,他会停止运算并返回该部分,也就是,返回undefinednull。
   用法: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);
 
由于对nullundefined用!操作符时都会产生true的结果,
所以用两个感叹号的作用就在于,
如果明确设置了o中flag的值(非 null/undefined/0""/等值),自然test就会取跟o.flag一样的值;
如果没有设置,test就会默认为false,而不是 nullundefined

数组方法

slice(截取)

slice():返回从原数组中指定开始下标到结束下标之间的项组成的新数组。slice()方法可以接受一或两个参数,即要返回项的起始和结束位置。在只有一个参数的情况下, slice()方法返回从该参数指定位置开始到当前数组末尾的所有项。如果有两个参数,该方法返回起始和结束位置之间的项——但不包括结束位置的项。

image.png

splice(数组更新)

splice():很强大的数组方法,它有很多种用法,可以实现删除、插入和替换。

  • 1-添加元素:(三个元素)

    • 第一个参数表示从那个下标位置开始添加,第二个参数为0,第三个参数表示要添加的元素,可以存在多个
  • 2-替换元素:(三个元素)

    • 第一个参数表示从那个下标位置开始添加(包含下标开始的位置),第二个参数表示替换的长度,第三个参数表示用什么元素替换
  • 3-删除元素 (两个元素)

    • 第一个参数为开始删除的下标位置,第二个参数为删除的长度,第三个参数不填写

sort(排序)

  1. 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]

明显是错误的排序,可以传入比较函数来定义排序顺序

  1. 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()创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。

1filter() 不会对空数组进行检测;
2filter() 不会改变原始数组。

使用实例

     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 = [234]; 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() 方法用于判断字符串是否包含指定的子字符串。

image.png

语法:string.includes(searchvalue, start)

  • searchvalue 必需值,要查找的字符串。
  • start 可选值,设置从那个位置开始查找,默认为 0。

slice(截取)

slice(start, end) 方法可提取字符串的某个部分,并以新的字符串返回被提取的部分。

image.png

语法:string.slice(start,end)

  • start 必须。 要抽取的片断的起始下标,第一个字符位置为 0。如果为负数,则从尾部开始截取。
  • end 可选。 紧接着要截取的片段结尾的下标。若未指定此参数,则要提取的子串包括 start 到原字符串结尾的字符串。如果该参数是负数,那么它规定的是从字符串的尾部开始算起的位置。slice(-2) 表示提取原数组中的倒数第二个元素到最后一个元素(包含最后一个元素)。

split (分割)

split() 方法用于把一个字符串分割成字符串数组。

image.png

语法:string.split(separator,limit)

  • separator 可选。字符串或正则表达式,从该参数指定的地方分割 string Object。
  • limit 可选。该参数可指定返回的数组的最大长度。如果设置了该参数,返回的子串不会多于这个参数指定的数组。如果没有设置该参数,整个字符串都会被分割,不考虑它的长度。

concat(连接字符串)

concat() 方法用于连接两个或多个字符串。

该方法没有改变原有字符串,但是会返回连接两个或多个字符串新字符串

image.png

语法: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对象

image.png

以下方式新建Map对象的结果是一样的

// 创建对象
const apples = {name: 'Apples'};
const bananas = {name: 'Bananas'};
const oranges = {name: 'Oranges'};

// 创建新的 Map
const fruits = new Map([
  [apples, 500],
  [bananas, 300],
  [oranges, 200]
]);

image.png

实例的属性和操作方法

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)})

image.png

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";