面试之es6
let 和 const
- 使用var定于的变量为全局变量,也就是在window.XX变量都可以访问到:
- 作用域:
- JS中作用域有:全局作用域、函数作用域。没有块作用域的概念。
- ECMAScript 6(简称ES6)中新增了块级作用域。
- 块作用域由 { } 包括,if语句和for语句里面的{ }也属于块作用域
验证块级作用域
- 由于var 定义的变量为全局变量,var对于定义的变量或者函数有着变量的提升,对于单纯的变量值的话,则是一步到位,既提升定义值也赋值,于是会打印出 b 的值;(注意点:函数的变量提升,只是提升函数的定义,不提升函数的调用,需要根据执行消息队列之中,先执行一步一步执行同步任务等!)
- 由于let 和 const 存在块级作用域,不存在变量提升这回事,因此只是限制在定义的块级作用域内可以访问!(注意点:在内层块级作用域可以访问外层的变量,这涉及到作用域链的访问)
- let 定义的变量,在块级作用域内,只能定义一次,否者会提示XX变量 has already been declared 已经被定义了(注意点:let定义的变量,可以修改所定义的值)
- const定义的变量,具有块级作用域,在块级作用域内只能定义一次,否者提示已被定义了,值得注意的是const定义的变量是只读的,不可修改的,否者会提示 XXX is read-only
<template>
<div></div>
</template>
<script>
export default {
data() {
return {};
},
created() {
this.init();
},
methods: {
init() {
{
var b = 10;
let c = 20;
// let c; c has already been declared
const d = 30;
// d = 40; // "d" is read-only
console.log("内b", b, "内c", c, "内d", d); //内b 10 内c 20 内d 30
{
console.log("第二层内c", c); // 第二层内c 20
}
}
console.log("外b", b); //外b 10
// console.log("外c", c); // 报错 c is not defined
// console.log("外d", d);// 报错 d is not defined
var aArr = [];
for (var i = 0; i < 5; i++) {
aArr[i] = function () {
console.log(i);
};
}
aArr[4](); // 5
// 由于var 定义的变量为全局变量,在for循环结束后,i为5
let bArr = [];
for (let i = 0; i < 5; i++) {
bArr[i] = function () {
console.log(i);
};
}
bArr[4](); // 4 由于let定义的变量具有块级作用域,函数里面的i值是没有被覆盖的,因此在取数时候,依旧原本没有被覆盖的值
},
},
};
</script>
箭头函数
() => {}
1: 改变this的指向,承接上下文
2:若是只有一条语句,可以省去return
3:没有arguments,省去内部使用arguments造成的问题
4:若是只有一个参数,可以省略()
5: 箭头函数没有prototype属性
变量结构赋值
数组的解构
- 根据数组对应的顺序进行解构,若是对应有值,则解构出对应的值,若是没有值,则解构的值为
undefined
- 数组可以针对嵌套的数组进行解构
- 数组解构时,可以设置默认值(**注意点:就是ES6 内部使用严格相等运算符(=)只有在值为undefined时,才使得默认值实现,但是null值 ! undefined **)
// 数组的解构:
let a = [1, 2, 3, [4]];
let b = [];
let [a1, a2, a3, a4] = a;
let [b1, b2] = b;
console.log("a之a1", a1, "a2", a2, "a3", a3, "a4", a4); // a之数组结构的a1 1 a2 2 a3 3 a4 4
console.log("b1", b1, "b1判", b1 ? b1 : ""); // b1 undefined b1判
console.log("b2", b2, "b2判", b2 ? b2 : ""); //b2 undefined b2判
let [c, ...d] = [1, 2, 3, 4];
console.log("c", c, "d", d); // c 1 d [2,3,4]
let [x = "aaa", y] = [undefined, null];
console.log("x", x, "y", y); // x aaa y null
对象的解构
- 对象的解构是根据对象的所存在属性进行解构,没有对应属性时,解构的值为
undefined
- 其他同数组结构同理
// 对象的解构
let { a, b, c, d: dd, e = "e" }
= { a: "aaa", b: "bbb", d: "ddd",e:"eee" };
console.log("a", a, "b", b, "c", c, ); // a aaa b bbb c undefined
console.log("dd", dd,"e",e); // dd ddd e eee;
let obj = {
arr: [
"xxx",
{
y: "yyy",
},
],
};
let {
arr: [x, { y }],
arr: newA,
} = obj;
console.log("x", x, "y", y, "newA", newA); // x xxx y yyy newA ['xxx', {y: "yyy",}]
// 对象的结构
let obj3 = { x: 1, y: 2, z: 3, w: 4, q: 5 };
let { x, y, ...ww } = obj3;
console.log("x", x, "y", y, "ww", ww); // x 1 y 2 ww {z: 3, w: 4, q: 5}
字符串的新增方法
判断某个字符是否存在三种方法includes startsWith endsWith
- includes:判断字符串之中是否含有某个字符,返回值为布尔值
- startsWith:判断字符串之中以什么头部开始是否含有某个字符,返回值为布尔值
- endsWith:判断字符串之中以什么尾部结束是否含有某个字符,返回值为布尔值
- 注意点:就是这三个方法有着两个参数,第一个参数就是需要查找的值,第二个参数为位置;
- includes 与 startsWith 中的第二个参数,代表的是从第n个索引开始查找
- endsWith之中的第二个参数,则是代表的是0-第n个字符内查找
let str = "www 菜鸡www! 菜鸡2!.com!"; // 空格占一个字符
console.log("includes", str.includes("菜")); // includes true
console.log("startsWith", str.startsWith("www")); // startsWith true
console.log("endsWith", str.endsWith("!")); // endsWith true
console.log("includes-2", str.includes("菜", 5)); // includes-2 true
console.log("startsWith-2", str.startsWith("www", 6)); // startsWith-2 true
console.log("endsWith-2", str.endsWith("!", 4)); // endsWith-2 false
console.log("endsWith-2", str.endsWith("!", 10)); // endsWith-2 true
repeat将字符串重写几次
- 作用:就是对一个字符串重写几次,最后拼接在一起,返回组合值
let str = "xzl";
console.log("将字符串重复3回", str.repeat(3)); // 将字符串重复3回 xzlxzlxzl
清除字符串的空格trim trimStart trimEnd
- trim:ES5就有方法
- trimStart 、trimEnd:是ES2019(ES10的方法)
let str1 = " xzl";
let str2 = " xzl ";
console.log("清空1",str1.trim(""));
console.log("清空2",str1.trimStart(""));
console.log("清空3",str2.trimEnd(""));
// 清空1 xzl // trim 清空 字符串 左右两侧的空格
// 清空2 xzl // trimStart 清空 字符串 左侧的空格
// 清空3 xzl // trimEnd 清空 字符串 右侧的空格
全局匹配字符串的方法replaceAll
- replaceAll就是全局匹配字符串,然后替换为想要替换的值(ES2021)
let str = " xzlxzlxzl";
console.log("第一个匹配替换", str.replace("xzl", "菜鸡"));
// 第一个匹配替换 菜鸡xzlxzl
console.log("正则全局匹配", str.replace(/xzl/g, "渣"));
// 正则全局匹配 渣渣渣
// 使用es2021
console.log("replaceAll()", str.replaceAll("xzl", "小亮"));
// replaceAll() 小亮小亮小亮
Math新增的方法
Math.trunc() 去掉小数点
console.log("App-",Math.trunc(0.001)); // 0
Math.sign() 判断一个数字是正数、负数、还是0
- 判断一个数字是正数、负数、还是0 此函数共有 5 种返回值,分别是 1, -1, 0, -0, NaN. 代表的各是正数,负数,正零,负零,NaN
console.log("App-",Math.sign(0.001)); // 1
console.log("App-",Math.sign(-1)); // -1
console.log("App-",Math.sign(0)); // 0
console.log("App-",Math.sign(-0)); // -0
console.log("App-",Math.sign(true)); // 1
console.log("App-",Math.sign(NaN)); // NaN
数组的扩展方法
es6 数组方法
map, filter, reduce, some, every, includes, find, findIndex, flat,Array.from,Array.of,扩展运算符;
map => 遍历数组,对数组的item进行调整,返回操作后的数组(map不会影响原始数组)
`js
const arr = [1,2,3]
let newArr = arr.map(item => {
if ( item === 1 ) {
item = 10
}
return item
})
console.log('newArr',newArr); // [10, 2, 3]
`
filter => 遍历数组,匹配找出符合条件的 item,返回符合的数组(filter 不会影响原始数组) `arr = [1,2,3] let newArr = arr.filter(item => item > 2) newArr输出 [3]`
reduce => 遍历数组,一般用于计算数据 `reduce((prev,curv) => return prev + curv )`,返回累计操作的值(reduce 不会影响原始数组)
some => 遍历数组,用于判断数组集合是否有一个 item 符合条件,是则返回 true,否则返回 false(some 不会影响原始数组) `arr = [1,2,3] let flag = arr.some(item => item > 2) flag为true`
every => 遍历数组,用于判断数组集合是否每个 item 都符合条件,是则返回 true,否则返回 false(every 不会影响原始数组) `arr = [1,2,3] let flag = arr.every(item => item < 2) flag为true`
includes => 遍历数组,判断数组是否包含某个值,是则返回 true,否则 false `arr = [1,2,3]; arr.includes(3) `(includes 不会影响原始数组)
find => 遍历数组,寻找出符合条件的数据,找到第一个则直接返回当前找到是数据 `arr = [1,2,3]; arr.find(v=> v===3)`(find 不会影响原始数组)
findIndex => 遍历数组,寻找出第一个符合条件的数据索引 ` arr = [1,2,3] let newArr = arr.findIndex(item => item > 1) newArr为 1`(findIndex 不会影响原始数组)
flat => 二维数组的平铺,只针对二位数组 `arr = [1,2,[3]] let newArr = arr.flat() newArr为[1,2,3]`(flat 不会影响原始数组)
Array.from => 把可遍历的数据转化为数组 `const obj = {0:'a' ,1:'b',length: 2} Array.from(obj); // ['a', 'b']`; `const arr = [1,2,3,3] Array.from( new Set(arr)) [1, 2, 3]`
Array.of => 把值转化为数组 `Array.of(1,2) 输出 [1,2]`
...扩展运算符 => ` arr: [1] arr2: [2] arr3 = [...arr,...arr2] 得到[1,2]`
对象的扩展方法
Object.is()对两个值的绝对判断
- 1:对两个值进行绝对的判断
- 2:可以正确的区分
+0
于-0
- 3:无法判断两个复杂对象,但是能判断两个复杂对象的值是否完全相等
- 4:针对NaN也可以做到绝对的相等
console.log("res1", Object.is("a", "a"));
console.log("res2", Object.is("+0", "-0"));
console.log("res3", Object.is({}, {}));
console.log("res4", Object.is({ age: 20 }, { age: 20 }));
console.log("res5", Object.is(NaN, NaN));
let obj1 = {age:10}
let obj2 = {age:10}
console.log("res6", Object.is(obj1.age, obj2.age));
// res1 true
// res2 false
// res3 false
// res4 false
// res5 true
// res6 true
Object.assign()对象的合并,针对第一个目标对象扩展出新的对象
- 1:Object.assign( tar , obj1 obj2 。。。 )
- 2:参数1:tar > 这是目标对象,需要被扩充的对象,针对后面的几个对象数据,一起合并到当前目标对象之中!
- 3:注意点:就是目标对象有着与后续对象相同的属性值,则取后续对象的属性值,作为最终结果!
- 4:若是只有目标对象,最终返回目标对象,也就是没有参与扩展对象属性
- 5:若是参数不是对象,则先转化为对象,再返回转化后的对象值
注意点
:Object.assign()为浅拷贝,目标对象的属性值发生改变时候,会影响到当前合并对象的结果
let targetObj = { a: 1, b: 1 };
const obj1 = { b: 2 };
const obj2 = { c: 3 };
let res1 = Object.assign(targetObj, obj1, obj2);
console.log("res1", res1); // res1 {a: 1, b: 2, c: 3}
let res2 = Object.assign("11");
console.log("res2", res2); // res2 String {'11'}
Object.keys(obj)获取对象的属性,可用于清空当前对象的属性值
- 遍历当前对象,获取到当前对象的属性
- 返回结果:一个数组(由当前对象的属性值构成的元素)
let obj = {
name: "ppp",
age: 20,
sex: "男",
};
// 遍历对象 获取对象的属性值
Object.keys(obj).forEach((item) => {
console.log("item", item);
obj[item] = "";
});
// item name
// item age
// item sex
console.log("obj", obj); // {name: '', age: '', sex: ''} 遍历对象,把当前对象的属性值清空处理!
console.log("res2", Object.keys(obj)); // ['name', 'age', 'sex']
Object.values(obj2)遍历对象。返回数组(当前对象属性值作为每一个元素)
let obj2 = {
name: "ppp2",
age: 202,
sex: "男2",
address: "",
};
// 遍历对象 获取对象的属性值 返回一个属性值构成的数组
console.log("arr", Object.values(obj2)); // arr ['ppp2', 202, '男2', '']
链判断运算符?. 以及babel的最新转码配置
- 读取对象的某个属性,需要先判断当前属性是否存在,又得多费一步判断,但是有了
链判断运算符?. 后会节省很多
- 安装:
yarn add @babel/preset-env --dev
- .babelrc
.babelrc
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "entry"
}
]
]
}
使用
// es2020 链接判断符
let obj1 = {
a: 10,
b: {
body: {
user: "xzl",
},
},
};
let res = obj1?.b?.body?.user;
console.log("链接判断符", res);//链接判断符 xzl
Set
Set集合
- 特性:
类似于数组,但是成员的值都是唯一的,没有重复的值
- 作用1:可以用于简单数据类型的值的去重(数组内的)、同理也可以用于字符串的去重
set的实例方法
add(value) 添加一个值
delete(value) 删除一个值
has(value) 判断是否存在某个值
clear() 删除所有的值
keys() 返回遍历器
values() 返回遍历器
entries() 返回遍历器
forEach() 用于遍历
size 属性 获取Set成员的个数
const set = new Set([1, 2, 3, 1])
console.log('res,', set, '; set-arr', [...set]) // res, Set(3) {1, 2, 3} ; set-arr (3) [1, 2, 3]
set.add(4)
console.log('set-res', [...set]) // [1, 2, 3, 4]
set.add(4).add(6)
console.log('set-res', [...set]) // [1, 2, 3, 4, 6]
set.delete(4)
console.log('set-res', [...set]) // [1, 2, 3, 6]
console.log('set-res', set.has(4), set.has(6)) // set-res false true
// for (let item of set.keys()) {
// console.log(item)
// }
// 1 2 3 6
// for (let item of set.values()) {
// console.log(item)
// }
// 1 2 3 6
// for (let item of set.entries()) {
// console.log(item)
// }
// [1, 1] [2,2] [3,3] [6,6]
// set.forEach(item=>{ console.log(item);})// 1 2 3 6
console.log("长度", set.size); // 长度 4
set.clear()
console.log('set-res', [...set]) // []
set的使用( 简单数组的去重,字符串的去重 )
// Set 类似于数组,但是成员的值都是唯一的,没有重复的值
let arr = [1, 1, 22, 2, 3, 3, 1, 7];
console.log("res", new Set(arr), "arr", [...new Set(arr)]);
// res {1, 22, 2, 3, 7} arr [1, 22, 2, 3, 7]
// 注意点:Set只针对存储在栈的简单数据类型中唯一没有重复的值,但是对对象则不涵盖之!
let arr2 = [{ name: "ppp" }, { name: "ppp" }];
console.log("arr2", new Set(arr2)); // arr2 [{ name: "ppp" }, { name: "ppp" }];
// 可以用于字符串的去重
let str = "aabbccds";
let res3 = [...new Set(str)].join("");
console.log("res3",res3);// res3 abcds
Map
- 描述
Object对象是一种键值对(key-value)的集合,属性名就是键(key),属性值就是值(value)
Map类似于对象,也是键值对的集合,对象的Key只能是字符串和Symbol类型,Map的Key可以是任意类型
Map实例方法
get(key) 获取指定key的值
set(key,value) 设置或添加某个key的值
delete(key) 删除指定的某个key和他值
clear() 清空所有
has(key) 判断某个key是否存在
keys() 返回遍历器,所有key的集合
values() 返回遍历器,所有值的集合
entries() 返回遍历器,所有key-value的集合(二维)
forEach() 用于遍历
let map = new Map()
console.log('map', map) //创建空的 Map(0) {size: 0}
let map1 = new Map([
['a', '111'],
['b', '222']
])
console.log('map1', map1) //创建的时候,指定初始值 map1 Map(2) {'a' => '111', 'b' => '222'}
console.log(map1.get('a')) // 111
console.log(map1.set('b',333)); // Map(1) {'b' => 333}
console.log("map1",map1); // map1 Map(2) {'a' => '111', 'b' => 333}
console.log(map1.delete('a')); // true -> 删除成功
console.log("map1",map1); // map1 Map(1) {'b' => 333}
console.log(map1.clear()); // undefined
console.log("map1",map1); // map1 Map(0) {size: 0}
let map2 = new Map([
['a', '111'],
['b', '222']
])
console.log('has',map2.has('a')); // has true
for (const item of map2) {
console.log("item",item);
}
// ['a', '111'] ['b', '222']
for (const item of map2.keys()) {
console.log("item",item);
}
// a b
for (const item of map2.values()) {
console.log("item",item);
}
// 111 222
for (const item of map2.entries()) {
console.log("item",item);
}
// ['a', '111'] ['b', '222']
map2.forEach(item=> console.log(item)) // 111 222
Promise
const fun = () => {
return new Promise((resolve,reject) => {
setTimeout(()=>{
resolve({code:200})
},300)
})
}