目录
let和const命令
es6新增了两个声明变量的关键字:let和const;
- var声明存在变量提升问题,let和const不存在变量提升
-
console.
log(a);
// undefined 变量提升了 实际代码变为 var a; console.log(a)
-
console.
log(b);
// 报错 Uncaught ReferenceError: Cannot access 'b' before initialization
-
console.
log(c);
// 报错 Uncaught ReferenceError: Cannot access 'c' before initialization
-
var a =
120;
-
let b =
'false';
-
const c =
100;
- let和const只能在块作用域里访问
-
// 使用var
-
var arr = [];
-
for (
var i =
0; i <
10; i++) {
-
arr[i] =
function(
) {
-
return i
-
};
-
}
-
console.
log(arr[
5]());
// 10
-
-
-
// 使用let或const
-
const arr = [];
-
for (
let i =
0; i <
10; i++) {
-
arr[i] =
function(
) {
-
return i
-
};
-
}
-
console.
log(arr[
5]());
// 5
-
if(
true) {
-
var a =
120;
-
let b =
'false';
-
const c =
100;
-
}
-
console.
log(a);
// 120
-
console.
log(b);
// 报错:Uncaught ReferenceError: b is not defined
-
console.
log(c);
// 报错:Uncaught ReferenceError: c is not defined
- 同一作用域下let和const不能声明同名变量,而var可以
-
var a =
120;
-
let b =
'false';
-
const c =
100;
-
var a =
130;
-
let b =
'true';
// Uncaught SyntaxError: Identifier 'b' has already been declared
-
const c =
200;
// Uncaught SyntaxError: Identifier 'c' has already been declared
-
console.
log(a);
// 130
- const只能定义常量,而且不能修改
-
const b =
false;
-
b =
12;
-
console.
log(b);
// Uncaught TypeError: Assignment to constant variable
- 不会污染全局变量
-
console.
log(
window.
RegExp);
// ƒ RegExp() { [native code] }
-
let
RegExp =
10;
-
console.
log(
RegExp);
// 10
-
console.
log(
window.
RegExp);
// ƒ RegExp() { [native code] }
模板字符串
使用反引号``来创建模板字符串,插入变量时使用${变量名};
-
let name =
'小明';
-
let age =
'12';
-
console.
log(name +
'今年'+ age +
'岁啦!');
// 小明今年12岁啦!
-
console.
log(
`${name}今年${age}岁啦!`);
// 小明今年12岁啦!
使用该方法可避免了大量+ 和 ' '的配合使用;
扩展运算符
扩展运算符是指...,用于扩展可迭代类型或数组;
- 使用扩展运算符合并数组
-
const arry1 = [
'小明',
'小红'];
-
const arry2 = [...arry1,
'小李',
'小强'];
-
console.
log(arry2);
// ['小明', '小红', '小李', '小强']
- 使用扩展运算符拷贝数组
-
const arry1 = [
'小明',
'小红'];
-
const arry2 = [...arry1];
-
console.
log(arry2);
// ['小明', '小红']
-
arry2[
2] =
'小强';
-
console.
log(arry1, arry2);
// ['小明', '小红'] ['小明', '小红', '小强']
使用扩展运算符拷贝的结果不是简单拷贝的引用地址,因此改变不会受影响;
- 带对象的扩展运算符
-
const obj1 = {
name:
'小明',
age:
12};
-
const obj2 = {
hobby:
'踢足球'};
-
const obj3 = {...obj1, ...obj2}
-
console.
log(obj3);
// {name: '小明', age: 12, hobby: '踢足球'}
对象扩展运算符,层数是1的话为深拷贝。二级以上的层级则不是深拷贝;
-
const obj1 = {
name:
'小明',
age:
12};
-
const obj2 = {
-
project: {
-
English:
20,
-
huaxue:
30,
-
}
-
};
-
const obj3 = {...obj1, ...obj2}
-
console.
log(obj3);
// {name: '小明', age: 12, hobby: '踢足球'}
-
obj3.
project.
huaxue =
90
-
console.
log(obj2);
// project: {English: 20, huaxue: 90} obj2的huaxue属性也被改变了
-
console.
log(obj3);
// {name: '小明', age: 12, project: {English: 20, huaxue: 90}
解构赋值
解构赋值是对赋值运算符的一种扩展,它是一种针对数组或对象进行模式匹配,然后对其中的变量进行赋值,可使代码简洁易读;
对象解构
-
let student = {
-
name:
'小凡',
-
age:
18
-
}
-
let {name, age} = student
-
console.
log(name, age);
// 小凡 18
对象解构时左侧变量名要与对象中key值对应,用{}
-
let student = {
-
name:
'小凡',
-
age:
18
-
}
-
let {name, age, sex} = student
-
console.
log(name, age, sex);
// 小凡 18 undefined
也可以进行非完全解构;
-
let student = {
-
name:
'小凡',
-
age:
18,
-
sex:
'男'
-
}
-
let {name} = student
-
console.
log(name);
// 小凡
可与扩展运算符搭配使用;
-
let student = {
-
name:
'小凡',
-
age:
18,
-
sex:
'男'
-
}
-
let {name, ...attribute} = student
-
console.
log(name, attribute);
// 小凡 {age: 18, sex: '男'}
所有的变量都放到扩展变量中;
-
let student = {
-
name:
'小凡',
-
age:
18,
-
sex:
'男',
-
school: {
-
name:
'一中',
-
location:
'村里'
-
}
-
}
-
let {name, school, ...attribute} = student
-
console.
log(name,school, attribute);
// 小凡 {name: '一中', location: '村里'} {age: 18, sex: '男'}
数组解构
数组解构使用[ ],左侧变量名任意;
-
let student = [
'小凡',
18,
'男'];
-
[name, age, sex] = student
-
console.
log(name, age, sex);
// 小凡 18 男
其它与对象解构一样;
扩展的函数
带参数默认值的函数
ES6添加了参数默认值,所以不用在函数内部编写容错代码;
-
// es5的写法
-
function
add(
a,b) {
-
a = a ||
10;
// 若无定义a,则默认为10
-
b = b ||
20;
// 若无定义b,则默认为20
-
return a+b
-
}
-
console.
log(
add());
// 30
-
-
// es6的写法
-
function
add(
a = 10, b = 20) {
-
return a + b
-
}
-
console.
log(
add());
// 30
剩余参数表示不定参
不定参功能和es5的arguments一样;
-
// es5写法
-
function
pick(
obj) {
-
let result = {};
-
for(
let i =
1; i <
arguments.
length; i++) {
-
result[
arguments[i]] = obj[
arguments[i]]
-
}
-
return result;
-
}
-
let book = {
-
name:
'活着',
-
author:
'余华',
-
pages:
400
-
}
-
let bookData =
pick(book,
'name',
'author',
'pages');
-
console.
log(bookData);
// {"name": "活着", "author": "余华","pages": 400}
-
function
pick(
obj, ...keys) {
-
let result = {};
-
for(
let i =
0; i < keys.
length; i++) {
-
result[keys[i]] = obj[keys[i]];
-
}
-
return result;
-
}
-
let book = {
-
name:
'活着',
-
author:
'余华',
-
pages:
400
-
}
-
let bookData =
pick(book,
'name',
'author',
'pages');
-
console.
log(bookData);
// {"name": "活着", "author": "余华","pages": 400}
箭头函数
在箭头函数中没有arguments,也没有prototype属性,箭头函数不是一个对象,所以不能用new关键字来实例化箭头函数;
它使用=>来定义,function() {} 等价于 () => {}
箭头函数的this指向用于指向其父级对象的this
扩展的对象
直接写入变量和函数,作为对象的属性和方法
-
// es6写法
-
const name =
"活着";
-
const author =
"余华";
-
-
const book = {
-
name,
-
author,
-
sayName(
) {
-
console.
log(
'这是一本很好看的书籍');
-
}
-
}
-
book.
sayName()
// 这是一本很好看的书
上面简写方式name,只能在属性和属性值相同的情况下简写~
-
// es5写法
-
const name =
"活着";
-
const author =
"余华";
-
-
const book = {
-
name: name,
-
author: author,
-
sayName:
function(
) {
-
console.
log(
'这是一本很好看的书籍');
-
}
-
}
-
book.
sayName()
// 这是一本很好看的书
新增Object.is()/Object.assign()/Object.keys/Object.value/Object.entries/Object.getOwnPropertyDescriptors方法
- Object.is()
Object.is()方法用来判断两个值是否严格相等,返回布尔值;与===区别在于对于NaN和+0、-0的处理结果不一样;
-
object1 = {
-
name:
'小明',
-
age:
12
-
}
-
object2 = {
-
name:
'小明',
-
age:
12
-
}
-
console.
log(object2.
name === object2.
name);
// true
-
console.
log(
Object.
is(object1.
name, object2.
name));
// true
-
console.
log(
null ===
null);
// true
-
console.
log(
Object.
is(
null,
null));
// true
-
console.
log(
NaN ===
NaN);
// false
-
console.
log(
Object.
is(
NaN,
NaN));
// true
-
console.
log(
Object.
is(+
0,-
0));
// false
-
console.
log(+
0 === -
0);
// true
-
// 补充几个烦人的比较
-
console.
log(
null
instanceof
Object);
// false,但null也是个对象
-
console.
log(
null ===
undefined);
// false
-
console.
log(
null ==
undefined);
// true
-
console.
log(
NaN ==
NaN);
// false
-
console.
log(
undefined ==
undefined);
// true
-
var x =
new
Boolean(
false);
-
console.
log(x);
// Boolean {false}
-
var y =
Boolean(
0);
-
console.
log(y);
// false
- Object.assign()
Object.assign()方法用于合并多个对象中的所有可枚举属性,并返回目标对象;是个浅拷贝方法~
-
object1 = {
-
name:
'小明',
-
age:
12
-
}
-
object2 = {
-
sex:
'male'
-
}
-
console.
log(
Object.
assign(object1, object2));
// {name: '小明', age: 12, sex: 'male'}
-
Object.keys()
Object.keys()用于返回对象中的所有属性,返回一个数组
-
object1 = {
-
name:
'小明',
-
age:
12
-
}
-
console.
log(
Object.
keys(object1));
// ['name', 'age']
- Object.values()
Object.values()用于返回对象中所有属性值,返回一个数组
-
object1 = {
-
name:
'小明',
-
age:
12
-
}
-
console.
log(
Object.
values(object1));
// [['小明', 12]
- Object.entries()
Object.entries()用于返回多个数组,每个数组都由key-value组成
-
object1 = {
-
name:
'小明',
-
age:
12,
-
classes: [
'语文',
'数学',
'英语']
-
}
-
console.
log(
Object.
entries(object1));
// [ "name","小明"],["age",12],["classes",["语文","数学","英语"] ] ]
- Object.getOwnPropertyDescriptors
该方法返回指定对象所有自身属性的描述对象;
-
<script>
-
const obj = {
-
name:
'xiaoming'
-
}
-
console.
log(
Object.
getOwnPropertyDescriptors(obj));
-
</script>
通过字面量创建出来的对象,默认可枚举属性enumerable为true,可配置属性configurable(是否可删除等属性)为true,writable属性为true;
补充:通过Object.creat()方法创建一个对象,使用现有的对象来作为新创建对象的原型prototype。
扩展的数值
- Number.EPSILON表示最小精度,一般用于判断小数是否相等
- Number.isFinite 用于检测一个数值是否为有限数值
- Number.isNaN 用于检测一个数值是否为NaN
- Number.parseInt 用于将字符串整数部分取出 Number.parseFloat将字符串中浮点数取出
- Number.isInteger 判断一个数值是否为整数
- Math.trunc 用于将数字的小数部分抹掉
- Math.sign 用于判断一个数到底为正数/负数还是0,正数返回1,负数返回-1,0返回0
-
console.
log(
0.1+
0.2 ===
0.3);
// false
-
// 但是可以写个函数 判断如果0.1+0.2 与0.3相差小于Number.EPSILON,则表明0.1+0.2 与0.3相等
-
console.
log(
Number.
isFinite(
100));
// true
-
console.
log(
Number.
isFinite(
100/
0));
// false
-
console.
log(
Number.
isFinite(
Infinity));
// false
-
console.
log(
Number.
isNaN(
NaN));
// true
-
console.
log(
Number.
isNaN(
0));
// false
-
console.
log(
Number.
parseInt(
'321flos3'));
// 321
-
console.
log(
Number.
parseInt(
'3.21flos3'));
// 3
-
console.
log(
Number.
parseFloat(
'3.21flos3'));
// 3.21
-
console.
log(
Number.
parseFloat(
'3.2.1flos3'));
// 3.2
-
console.
log(
Number.
isInteger(
3.21));
// false
-
console.
log(
Number.
isInteger(
'3'));
// false
-
console.
log(
Number.
isInteger(
3));
// true
-
console.
log(
Math.
trunc(
3.45));
// 3
-
console.
log(
Math.
sign(
3.45));
// 1
-
console.
log(
Math.
sign(-
3.45));
// -1
-
console.
log(
Math.
sign(
0));
// 0
Symbol
新增一种基本数据类型symbol,表示独一无二的值。特点如下:
symbol的值是唯一的,用来解决命名冲突的问题;
Symbol值不能与其他数据进行运算;
通过Symbol()或Symbol.for()创建Symbol值;
Symbol定义的对象属性不能使用for...in循环遍历,但是可以使用Reflect.ownKeys来获取对象的所有键名;
-
<script>
-
let s1 =
Symbol();
-
console.
log(s1,
typeof s1);
// Symbol() 'symbol'
-
// 带有标识的创建
-
let name =
Symbol(
'小明');
-
console.
log(name,
typeof name);
// Symbol(小明) 'symbol'
-
// 使用Symbol.for创建
-
let project =
Symbol.
for(
'英语');
-
console.
log(project,
typeof project);
// Symbol(英语) 'symbol'
-
</script>
一般在创建对象的某个属性唯一时,使用Symbol
-
<script>
-
const project =
Symbol()
-
const number =
Symbol()
-
let school = {
-
name:
'一中',
-
location:
'这里',
-
[project]:
function(
) {
-
console.
log(
'我喜欢英语');
-
},
-
[number]:
200
-
}
-
school[project]();
// 我喜欢英语
-
console.
log(school[number]);
// 200
-
</script>
Symbol是JavaScript中的第六种基本数据类型,与undefined、null、Number、String、Boolean并列~
Map和Set
Set
ES6提供了新的数据结构Set(集合),但成员的值都是唯一的,集合实现了iterator接口,所以可以使用扩展运算符和for...of...进行遍历;
Set对象的属性和方法主要有:
size: 返回集合的元素个数(相当于数组中的length属性);
add:增加一个新元素,返回当前集合;
delete:删除元素,返回布尔值;
has:检测集合中是否包含某个元素,返回布尔值;
-
let newSet =
new
Set([
1,
3]);
-
console.
log(newSet);
// Set(2) {1, 3}
-
console.
log(newSet.
add([
4,
5]))
// Set(3) {1, 3, [4, 5]}
-
console.
log(newSet.
delete(
3))
// true
-
console.
log(newSet.
delete(
4))
// false
-
console.
log(newSet.
has(
1))
// true
-
console.
log(newSet.
size);
// 2
- 利用Set对象唯一性的特点,可实现数组的去重~
-
let newSet = [...
new
Set([
1,
3,
3,
5,
4,
4,
6,
7])];
-
console.
log(newSet);
// [1, 3, 5, 4, 6, 7]
- 实现数组的交集~
-
let arr1 = [
1,
2,
3,
4,
5];
-
let arr2 = [
1,
4,
6,
7];
-
let arr3 = [...
new
Set(arr1)].
filter(
item =>
new
Set(arr2).
has(item))
-
console.
log(arr3);
// [1, 4]
- 实现数组的差集~
-
let arr1 = [
1,
2,
3,
4,
5];
-
let arr2 = [
1,
4,
6,
7];
-
let arr3 = [...
new
Set(arr1)].
filter(
item => !(
new
Set(arr2).
has(item)))
-
console.
log(arr3);
// [2,3,5]
- 实现数组的并集~
-
let arr1 = [
1,
2,
3,
4,
5];
-
let arr2 = [
1,
4,
6,
7];
-
let arr3 = [...
new
Set([...arr1, ...arr2])]
-
console.
log(arr3);
// [1, 2, 3, 4, 5, 6, 7]
Map
ES6提供了Map数据结构,是键值对的集合,键的定义不再像对象一样仅局限于字符串,而是包含各种类型的值(包括对象)。同时,因为Map实现了iterator接口,所以可以使用for...of进行遍历;
Map的属性和方法主要有:
size: 返回Map的元素个数
set:增加一个新元素,返回当前Map;
get:返回键值对象的键值;
has:检测当前Map中是否包含某个元素,返回布尔值;
clear:清空集合,返回undefined
-
let newMap =
new
Map();
-
newMap.
set(
'name',
'小明');
-
newMap.
set(
'classes', [
'语文',
'数学',
'英语']);
-
console.
log(newMap);
// Map(2) {'name' => '小明', 'classes' => Array(3)}
-
console.
log(newMap.
size);
// 2
-
console.
log(newMap.
has(
'name'));
// true
-
for (
const item
of newMap) {
-
console.
log(item);
// (2) ['name', '小明'] (2) ['classes', Array(3)]
-
}
-
console.
log(newMap.
delete(
'classes'));
// true
-
console.
log(newMap.
size);
// 1
-
console.
log(newMap.
get(
'name'));
// 小明
迭代器和生成器/Proxy对象
回头详细讲
Promise
见2023年了,你还在为Promise头疼?_迷糊的小小淘的博客-CSDN博客
类class
类的本质依然是一个函数
见JavaScript高级教程(面向对象编程)_迷糊的小小淘的博客-CSDN博客
模块化实现
模块化是为了将复杂的程序按照一定的规则拆分成单个文件,并最终组合在一起,可以降低代码复杂度,避免命名冲突,提高复用性;
ES6中的模块化功能主要由两个命令构成:export和import,export命令用于暴露模块的对外接口,import命令用于引入其它模块提供的功能;
导出模块有三种不同的暴露方式:
- 分别暴露方式
如果导出模块采用分别暴露的方式,如:
-
// test.js文件
-
// 通用暴露
-
export
let name =
'小明';
-
export
function
exam(
) {
-
console.
log(
'明天又要考试~');
-
}
- 统一暴露
如果导出模块采用统一暴露的方式,如:
-
// test.js文件
-
// 统一暴露
-
let name =
'小明';
-
function
exam(
) {
-
console.
log(
'明天又要考试~');
-
};
-
export {name, exam};
注意此处{name, exam}并不是表示解构赋值,只是表示一种写法~
则导入模块时要使用:
-
<script type=
"module">
-
// 通用暴露
-
import *
as m1
from
'./test.js'
-
// 给*起了别名m1
-
console.
log(m1);
// m1中包含name属性和exam方法
-
</script>
- 默认暴露
如果导出模块采用默认暴露的方式,该种方式一般应用于一个文件中只有一个暴露,如:
-
// test.js文件
-
// 默认暴露
-
export
default {
-
name :
'小明',
-
exam:
function(
) {
-
console.
log(
'明天又要考试~');
-
}
-
};
根据暴露模块的方法不同,引入模块也有不同的导入方式:
- 通用的引入方式
上述三种暴露方式都可使用该种方法:
-
<script>
-
// 通用暴露
-
import *
as m1
from
'm1.js'
-
// 给*起了别名m1
-
console.
log(m1);
// 对于前两种暴露方式m1中包含name属性和exam方法,
-
// 对于默认暴露方式,m1中包含default 取m1.default.name才可
-
</script>
- 解构赋值方式
对于前两种暴露方式,可直接通过下述代码拿到name或exam
-
<script type=
"module">
-
// 通用暴露
-
import { name,exam }
from
'./test.js'
-
// 或
-
import { name
as xingming,exam
as kaoshi }
from
'./test.js'
-
// 给name/exam起了别名
-
</script>
但是对于默认暴露来说,要采用如下:
-
<script type=
"module">
-
import {
default
as m1 }
from
'./test.js'
-
// 一般要给default取个别名,通过别名.name或别名.exam拿到
-
</script>
- 针对于默认暴露的简便导入方式
-
<script type=
"module">
-
import m3
from
'./test.js'
-
// 通过m3.name或m3.exam拿到
-
</script>
以上三种暴露方式可同时在另一个文件中引入,不会产生覆盖
此处,简单补充下另一个重要的模块化规范方式CommonJs:
CommonJs方式模块化的代码既可在服务器端,如nodejs中运行,又可以在浏览器端运行(需借助工具Browserify编译),他仅有两种暴露方式:
- exports.xxx = value, value是要暴露的数据,xxx是命名
- module.exports = value, value是要暴露的数据
原理是在服务端exports===module.exports={ },它俩都指向同一个空对象;
这两种方式不能混用,如果混用,则以module.exports暴露的为主,value是啥,module.exports暴露的就是啥;
显示并没有englishName这一属性,
引入方式也仅有两种,
- 引入第三方模块,require(xxx),xxx是模块名
- 引入自定义模块,require(xxx), xxx是模块文件路径
转载:https://blog.csdn.net/ks795820/article/details/127750467