一 、ES6简介
ES6, 全称 ECMAScript 6.0 ,是 JavaScript 的下一个版本标准,2015.06 发版。
由于常用es6
语法不多,有时需要查阅一些不常用的函数或特性,这里有一篇阮一峰的ES6 入门教程
二、ES6新增变量的定义
在没有学习ES6之前,我们都会用var来变量定义,其中,在ES6中新增的有let const
1.let关键字:
从直观的角度来说,let和var是没有太大的区别的,都是用于声明一个变量。
<script>
let str = 'hello world';
console.log(str);
</script>
2.const关键字:
const声明的变量称为常量,表示保存的数据一旦被赋值就不能再被修改了,但是如果是引用类型的数据,还是可以通过引用找到对应的对象进行修改的。
<script>
// 1 const 具有块级作用域
// if (true) {
// const num = 10;
// // console.log(num); //10
// }
// console.log(num) // num is not defined
// 2 声明常量时必须赋值
// const PI;
// console.log(PI)//Missing initializer in const declaration
// 3 常量赋值后 值不能修改 就是不能再次赋值了
// const PI = 3.14;
// PI = 10;
// console.log(PI) //Assignment to constant variable.
// 但是可以更改里面的内容 还是同一个储存空间 只是更改里面的内容
// 例如
const arr = ['red', 'green', 'pink']
arr.push('blue');
console.log(arr); //是正确的
</script>
-
注意:与var不同的是,let和const是不允许重复声明变量的。并且使用let和const声明的变量是具有自己的块级作用域的。var和let可以不设置初始值,const必须设置。
三、解构赋值
<script>
//对象解构赋值(遵守的规则:变量的名字必须和对象的key一致)
let obj = {
a: "a",
b: "b"
}
let { a, b } = obj; //等同于 let a = obj.a;let b = obj.b;
//数组解构赋值(数组下标位置必须一样)
let arr = ["1", "2", "3"];
let [a, b] = arr;
//字符串解构赋值(等同数组,位置一致)
let str = "abc";
let [a, b] = str;
</script>
四、箭头函数
<script>
//箭头函数表达式的语法比函数表达式更简洁,并且没有自己的this,arguments,super或new.target。箭头函数不能用作构造函数
function fn(param) { return param } //相当于 (param)=>param
//语法1:只有一个参数时"()"可以省略 param =>param
//语法2:函数体是表达式时 (param)=>{console.log(param)}
//语法3:加括号的函数体返回对象字面量表达式 param => ({a: "a"})
//语法4:不支持arguments,可使用剩余参数接收不定参 (param,...params)=>{console.log(params)}
//语法5:箭头函数不能作为构造函数,不能new
//this指向问题:
//普通函数:this指向函数调用者,默认情况下指向window;在严格模式下的函数调用下,this指向undefined;通过call,apply,bind绑定时,指向绑定的对象。
//箭头函数:没有自己的this,默认指向定义它时所在的对象的this,即父级的this。
//例:首先,在window下定义普通函数和箭头函数
function fnA() {
console.log(this)
}
let fnB = () => {
console.log(this)
}
fnA() //window
fnB() //window
//这时两个函数this都指向window,然后我们把箭头函数定义在函数内,方便改变父级this指向
let fnD;
let fnC = function () {
console.log(this)
fnD = () => {
console.log(this)
}
}
fnC() //window
fnD() //window
//这时调用两个函数,普通函数依旧指向调用它的对象,也就是window,箭头函数fnD的this继承了它父级fnC的this。
// 此时,我们改变fnC的指向,通过bind函数指向body
fnC = fnC.bind(document.body)
fnC() //body
fnD() //body
//此时打印结果也证明了,箭头函数的this指向始终与其父级this指向一致
</script>
五、数组新增的操作方法(数组的拓展)
1.拓展运算符('...'),它相当于rest参数的逆运算,用于将一个数组转换为用逗号分隔的参数序列;
<script>
console.log(...[1, 2, 3])
// 1 2 3
console.log(1, ...[2, 3, 4], 5)
// 1 2 3 4 5
</script>
.如果扩展运算符后面是一个空数组,则不产生任何效果
[...[], 1]
// [1]
2.常见的拓展运算符的应用:
//合并数组
let arr1 = [1,2];
let arr2 = [3,4];
let arr3 = [5,6];
let newArr = [...arr1 , ...arr2 , ...arr3]; //等同于ES5 [].concat( arr1 , arr2 , arr3 )
// [1,2,3,4,5,6]
//与解构赋值结合(用于生成数组)
const [ val , ...rest] = [1, 2, 3, 4, 5];
val // 1
rest // [2, 3, 4, 5]
//将字符串转为真正的数组
let str = 'mine';
[...str] // ["m","i","n","e"]
//可以将类数组转化成正真的数组
let arrayLike = {
0 : 'div.class1' ,
1 : 'div.class2' ,
2 : 'div.class3' ,
length : 3
}
console.log([...arrayLike]) // ["div.class1","div.class2","div.class3"]
3.新增 Array.from 方法,可以将类似数组的对象(array-like object)和可遍历(iterable)的对象转化成真正的数组;该方法还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理,将处理后的值放入返回的数组
let arr = [ 1 , 2 , 3];
arr.map( x => x * x);
// [ 1 , 4 , 9 ]
Array.from(arr, (x) => x * x)
// [ 1 , 4 , 9 ]
4.新增 Array.of 方法 ,用于将一组值,转换为数组(该方法基本上可以用来替代Array()或new Array(),避免出现参数不同而导致的重载);
//传统Array
Array() // []
Array(3) // [, , ,]
Array(1, 2, 3) // [1, 2, 3]
//Array.of
Array.of() // []
Array.of(undefined) // [undefined]
Array.of(1) // [1]
Array.of(1, 2) // [1, 2]
六、字符串新增方法
<script>
//str.includes:判断字符串中是否包含一个指定的值;
//参数:value用来查找的值 index[可选]开始查找的位置,负数则表示倒数位置
//返回值:Boolean
//使用:
"123".includes("2") // true
//str.startsWith:判断字符串是否已另一个字符串开始;
//参数:str 要搜索的字符串 index[可选]开始查找的位置
//返回值:Boolean
//使用:
"123".startsWith("1") // true
//str.endsWith:判断字符串是否已另一个字符串结束;
//参数:str 要搜索的字符串 length[可选]字符串长度,默认str.length
//返回值:Boolean
//使用:
"123".endsWith("1") // false
//str.repeat:重复原字符串;
//参数:count 要重复的次数,小数会取整,小于-1报错
//返回值:Boolean
//使用:
"123".endsWith("1") // false
</script>
七、模板字符串
<script>
//模板字符串使用反引号 (` `) 来代替普通字符串中的用双引号和单引号。
// 用(${ })将变量括起来,特殊字符需要加(\)进行转义。
//例:
let money = 100
let str1 = "本次消费" + money + "元"
let str2 = `本次消费${money}元`
console.log(str1, str2) //本次消费100元 本次消费100元 //这两种字符串拼接方式等同
</script>
八、对象新增内容
1. Object.is()
ES5 比较两个值是否相等,只有两个运算符:相等运算符
( == )和严格相等运算符
( === )。它们都有缺点,前者会自动转换数据类型,后者的 NaN 不等于自身,以及 +0 等于 -0 。JavaScript 缺乏一种运算,在所有环境中,只要两个值是一样的,它们就应该相等。
ES6 提出“Same-value equality”
(同值相等)算法,用来解决这个问题。Object.is
就是部署这个算法的新方法。它用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。
<script>
console.log(Object.is('foo', 'foo'));
// true
console.log(Object.is({}, {}));
// false
</script>
不同之处只有两个:一是 +0 不等于 -0 ,二是 NaN 等于自身。
<script>
console.log(+ 0 === -0); //true
console.log(NaN === NaN); // false
console.log(Object.is(+0, -0));// false
console.log(Object.is(NaN, NaN)); // true
</script>
ES5 可以通过下面的代码,部署 Object.is 。
<script>
Object.defineProperty(Object, 'is', {
value: function (x, y) {
if (x === y) {
// 针对+0 不等于 -0的情况
return x !== 0 || 1 / x === 1 / y;
}
// 针对NaN的情况
return x !== x && y !== y;
},
configurable: true,
enumerable: false,
writable: true
});
</script>
2. Object.assign()
2.1基本用法
Object.assign
方法用于对象的合并,将源对象
(source)的所有可枚举
属性,复制到目标对象(target)。
<script>
const target = { a: 1 };
const source1 = { b: 2 };
const source2 = { c: 3 };
Object.assign(target, source1, source2);
console.log(target); // {a:1, b:2, c:3}
</script>
Object.assign 方法的第一个参数是目标对象,后面的参数都是源对象。
注意,如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。
九、Symbol的解析与运用
1.概述
ES6
引入了一种新的原始数据类型Symbol
,表示独一无二的值。它是 JavaScript 语言的第七
种数据类型,前六种是: undefined 、 null 、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。
2.创建 Symbol
要创建一个 Symbol,你可以使用 Symbol()
函数。你还可以为 Symbol 提供一个可选的描述(字符串),用于调试和识别。需要注意的是,Symbol
函数不能使用 new
关键字来调用,否则会抛出一个错误。
const symbol1 = Symbol('description');
const symbol2 = Symbol('description');
console.log(symbol1); // Symbol(description)
console.log(symbol1 === symbol2); // false
虽然 symbol1
和 symbol2
的描述相同,但它们是不相等的,因为每个 Symbol
都是唯一的。
3.使用 Symbol 作为对象属性键
const person = {
name: 'John',
age: 30,
[Symbol('hobby')]: 'Programming'
};
console.log(person); // { name: 'John', age: 30, Symbol(hobby): 'Programming' }
在这个例子中,我们创建了一个对象 person
,其中使用了一个 Symbol
类型的属性键。这个属性键是唯一的,不会与其他属性名冲突。
需要注意的是,使用 Symbol
作为属性键时,这个属性不会出现在普通的属性枚举中(例如 for...in
循环或 Object.keys()
方法)
for (const key in person) {
console.log(key); // 输出 'name' 和 'age',不会输出 Symbol(hobby)
}
为了访问和枚举 Symbol 属性,你可以使用 Object.getOwnPropertySymbols()
方法或 Reflect.ownKeys()
方法。
const symbolKeys = Object.getOwnPropertySymbols(person);
console.log(symbolKeys); // [ Symbol(hobby) ]
const allKeys = Reflect.ownKeys(person);
console.log(allKeys); // [ 'name', 'age', Symbol(hobby) ]
十.set和map
1.set
1.1.特性
- 类似于数组,但是成员的值都是唯一的,没有重复的值。
Set
函数可以接受一个数组(或者具有iterable
接口的其他数据结构)作为参数,用来初始化。- 内部两个数据是否相同基本和
===
类似,区别是在Set
中NaN
和NaN
也是相等的。
1.2.应用
- 数组或字符串去重。
[...new Set([1, 1, 2, 3])] // [1, 2, 3]
[...new Set('ababbc')].join('') // "abc"
- 某些需要唯一性的数据,例如:用户名,
id
等。
1.3.Set实例的属性和方法
Set
结构的实例有以下属性。
Set.prototype.constructor:构造函数,默认就是 Set 函数。
Set.prototype.size:返回Set实例的成员总数。
- 操作方法(用于操作数据)
Set.prototype.add(value):添加某个值,返回 Set 结构本身。
Set.prototype.delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
Set.prototype.has(value):返回一个布尔值,表示该值是否为 Set 的成员。
Set.prototype.clear():清除所有成员,没有返回值。
- 遍历方法(用于遍历成员)
Set.prototype.keys():返回键名的遍历器
Set.prototype.values():返回键值的遍历器
Set.prototype.entries():返回键值对的遍历器
Set.prototype.forEach():使用回调函数遍历每个成员
2.Map
- 由于传统的
Object
对象只能使用字符串当作键,所以新增的Map
结构可以将各种类型的值(包括对象)都可以当作键。
const m = new Map();
const o = {p: 'Hello World'};
m.set(o, 'content')
m.get(o) // "content"
2.1.方法
- 相比
Set
的操作方法,Map
没有add
方法,新增了get
方法和set
方法。遍历方法则是基本是一样的。
Map.prototype.get(key) // 读取key对应的键值,如果找不到key,返回undefined。
Map.prototype.has(key) // 返回一个布尔值,表示某个键是否在当前 Map 对象之中。
2.2.转换
(1) Map
和数组
- 在第二弹中也提到了
Map
和数组之间转换,他们之间互转是很方便的。
// Map转为数组
const myMap = new Map()
.set(true, 7)
.set({foo: 3}, ['abc']);
[...myMap]
// [ [ true, 7 ], [ { foo: 3 }, [ 'abc' ] ] ]
// 数组转为 Map。
new Map([
[true, 7],
[{foo: 3}, ['abc']]
])
// Map {
// true => 7,
// Object {foo: 3} => ['abc']
// }
(2) Map
和对象
Map
的键都是字符串,它可以无损地转为对象。如果有非字符串的键名,那么这个键名会被转成字符串,再作为对象的键名。对象转为Map
可以通过Object.entries()
。
// Map => Object
function strMapToObj(strMap) {
let obj = Object.create(null);
for (let [k,v] of strMap) {
obj[k] = v;
}
return obj;
}
const myMap = new Map()
.set('yes', true)
.set('no', false);
strMapToObj(myMap)
// { yes: true, no: false }
// Object => Map
// let obj = {"a":1, "b":2};
let map = new Map(Object.entries(obj));
3.应用
- 在存储的数据是键值对的时候,并且键名的类型可能是多种类型是可以使用
Map
结构。与java
中的Map
结构有区别。