ES6的基本概念
ECMAScript6(以下简称ES6)是JavaScript语言的下一代标准,已经在2015年6月正式发布了。Mozilla公司将在这个标准的基础上,推出JavaScript 2.0。
ES6的目标,是使得JavaScript语言可以用来编写大型的复杂的应用程序,成为企业级开发语言。
了解一下ES6的那些新特性:
1.let和const声明变量
在ES6之前我们没次声明变量用的都是var关键字,var有个特点就是变量的提升,无论你在哪里声明的变量都会被视为声明在函数的最顶部(不在函数内即在全局作用域的最顶部)。
前后两段代码的含义是相同的。而在ES6中为了解决这些问题有了新的声明变量的方式。那就是let和const。而let、const和var有什么不同呢?
我们知道在以前我们不管是变量还是常亮我们都用var声明而现在我们一般用let 表示变量、const 表示常量。并且let 和 const 都是块级作用域。怎么理解这个块级作用域?
所谓块级作用域就是说你声明的变量仅在一个{}内有效。在{}外是无法调用的。
用let声明的变量无法被调用会报出 is not defined的提示。
其实用let和用var声明的表变量没有很直观上的区别,只是let声明的变量被限制在特定的范围内使用。
const则很直观,用来定义常量,即无法被更改值的变量。
2.箭头操作符(箭头函数)
我们知道在JS中经常要定义或者回调函数,那么没次定义函数的时候都要用function十分麻烦,ES6中引入了箭头函数具体使用方法如下:
特别强调一点的是如果箭头函数中只有一个形参或者函数体中只有一个语句(非return)语句时()和{}也可以省略,如果只有一个return语句则return也可省略。所以大家看到类似下表面代码格式时要注意。改进代码如下:
其次还有一个至关重要的一点,那就是箭头函数中,没有this。如果你在箭头函数中使用了this,那么该this一定就是外层的this。
也正是因为箭头函数中没有this,因此我们也就无从谈起用call/apply/bind来改变this指向。记住这个特性,能让你在react组件之间传值时少走无数弯路。
var person = {
name: 'tom',
getName: function() {
return this.name;
}
}
// 我们试图用ES6的写法来重构上面的对象
const person = {
name: 'tom',
getName: () => this.name
}
// 但是编译结果却是
var person = {
name: 'tom',
getName: function getName() {
return undefined.name;
}
};
复制代码
在ES6中,会默认采用严格模式,因此this也不会自动指向window对象了,而箭头函数本身并没有this,因此this就只能是undefined,这一点,在使用的时候,一定要慎重慎重再慎重,不然踩了坑你都不知道自己错在哪!这种情况,如果你还想用this,就不要用使用箭头函数的写法。
// 可以稍做改动
const person = {
name: 'tom',
getName: function() {
return setTimeout(() => this.name, 1000);
}
}
// 编译之后变成
var person = {
name: 'tom',
getName: function getName() {
var _this = this; // 使用了我们在es5时常用的方式保存this引用
return setTimeout(function () {
return _this.name;
}, 1000);
}
};
复制代码
3.默认值参数
在ES6中可以在定义函数的时候指定参数的默认值了,不像以前需要使用逻辑操作符来实现。
注意:这样的写法是错误的
4.新的两种数据结构Set和Map
1.Set
set和数据类似,也是一种集合,它们的区别在于:set里的值都是唯一的没有重复的。
var arr = [1,1,2,2,true,"hello",true]
var s1 = new Set([1,2,3,true,"hello"])
var s1 = new Set({name :“Cason”})
如果在Set中定义相同的值会报错。
用add()向Set集合中添加内容:
var s1 = new Set();
s1.add(1)
s1.add("Hello")
遍历上边的s1不能使用for in 需要使用foreach
s1.forEach(item=>console.log(item)
或者使用for of
for(var p of s1){
console.log(p)
}
Set是一个伪数组,并不是一个真的数组。
2.Map
Map类似于对象,它里边存放的也是键值对,但不同于对象的是,对象中的键名只能是字符串,而Map中的键可以是任意值。
var m = new Map([["a","hello"],[1,"123"]]);
m.set(flese,"abc")
m.set([1,2,3],{name:"Cason"})
5.模板字符串
ES6中允许使用反引号``来创建字符串,此种方法创建的字符串里面可以包含由美元符号加花括号包裹的变量${vraible}。
//产生一个随机数
var n = Math.random();
//将这个数字打印出来
console.log(‘这个随机数是${n}’)
ES6中还多了许多方法关于操作字符串例如:
1.trim 去掉字符串的左右空格还可以使用trimLeft和trimRi ght单独去掉一边的空格。
2.repeat 连续输出相同字符串str.repeat(打印的数量)。
3.includes 判断一个字符是否存在于某个字符串内。
4.startsWidth 判断字符串是否以某些字符开头相关的还有endsWidth。
6.数组
在ES6中数组添加了许多实用的方法
1.Array.from()
这个方法是Array构造器的静态方法。用来把类数组对象转化成真正的数组。
格式:Array.from(类数组对象)
或者:Array.from(类数组对象,function(item,index){
return;
}
2.Array.of 将一组值转换为数组。与Array.from功能相似,主要用来创建数组,主要目的是为了弥补Array()构造器的不足。
Array.of(类数组变量)
3.find和findIndex
find:用于找出第一个符合条件的数组元素。找不到则是 undefined 。注意,它是不会返回多个,只找一个,找到了就返回。如果你要把所有的满足条件的数组元素素都找出来,你应该用filter()
let arr = {
{name: "04"},
{name: "01"},
}
let as = arr.find(item => item.name == "01")
复制代码
返回值是整个元素
4.includes 判断元素是否在数组中存在。返回值是 true|false。
注意:indexof也可以做类似的工作但是indexof对NAN的判断是错误的,但includes可以很好的解决整个问题。
5.fill 给数组填充指定值。fill方法用于空数组的初始化非常方便。已有数据会被覆盖。fill方法还可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置。
可以覆盖之前的元素
可以指定位置进行填充fill中的三个参数分别为数据、起点、终点。
6.数组的扩展运算符Spread Operator
Spread Operator(...)把数据结构转换成数组
var arr2 = [ ...arr ]; [ ]表示一个数组。即 arr2 是一个数组。 ...arr :把数组 arr 展开。分解成一个一个的元素 相当于实现了,数组的复制---这里是浅拷贝
7.数组的解构赋值
在ES6允许按照一定的模式,从数组或对象中提取值,对变量进行赋值,这被称为解构。是对变量的赋值,变量的值是数组或或对象。
let arr = [i,2,3]
let a = arr[0]
let b = arr[1]
let c = arr[2]
然而我们有更好的方法:
let [a,b,c] = [1,2,3];
console.log(a)
console.log(b)
console.log(c)
需要注意的是“=”两边的结构要一样。
当数组中长度不足时:
let [a,b,c,d = 60] = [1,2,3];
可以成功赋值。
嵌套:
可以在一个数组里边添加一个数组:
let [a,b,[c]] = [1,2,[22]];
8.拓展对象功能
在ES5中对象都是以键值对的形式书写可能出现键值重名现象。 属性名是可以简写的,但是有前提条件:
1.属性的值是一个变量
2.变量名称和键名是一致的。
创建一个对象:
var obj = {
name : "Cason",
age:666,
say:function(){
console.log("say.....")
}
}
复制代码
当我们的键值重名时键名可以省略。
function a(name,age){
return{
name,
age,
};
}
复制代码
方法的简写
var obj = {
name : "Cason",
age:666,
say(){
console.log("say.....")
}
}
复制代码
9.类的概念(class)
从形式上,向主流的面向对象的语言靠拢。我们之前写对象方式可以用 Class 用进行优化
之前我们都是创建构造器,然后去new构造器,构造器就相当于一个类,在ES6中,就可以使用class来创建对象了。
格式:
class 类名{
constructor(参数){
}
method(){
}
}
注意: class 是关键字,后面紧跟类名,类名首字母大写,采取的是大驼峰命名法则。类名之后是{}。在{}中,不能直接写语句,只能写方法,方法不需要使用关键字方法和方法之间没有逗号,不是键值对。
在ES6中用class声明一个类,如下:
class Cat{
constructor(name,age,type){
this.name = name;
this.age = age;
this.type = type;
}
say(){
console.log(`这是一只${this.type}`)
}
}
var c1 = new Cat("阿黄","1","橘猫")
复制代码
既然有了类的概念就不得不谈一下继承,在ES6中可以用extends来实现继承:
class Cat{
constructor(name,age,type){
this.name = name;
this.age = age;
this.type = type;
}
say(){
console.log(`这是一只${this.type}`)
}
}
class SEX extends Cat{
constructor(name,age,type,sex){
super(name,age,type)
this.sex = sex;
}
showSay(){
console.log(`这是一只${this.sex}猫`)
}
}
var c1 = new Cat("阿黄","1","橘猫")
var c2 = new SEX("大白","5","波斯猫","母")
c2.showSay()
复制代码
10.ES6之严格模式
之前学习的JS,语法非常灵活,JS中这个灵活的特性,弊大于先利。后来增加了严格模式。使用严格模式的目的:规则,提高编译效率。
怎么去启动严格模式: "use strict"
严格模式和非严格模式有什么区别:
1.在严格模式下不能使用没有var的变量。
2.在严格模式下不能8进制的数字。
3.在严格模式下不能把函数定义在if语句中。
4.在严格模式下函数不能有重名的形参。
5.在严格模式下不能arguments就不能使用了。
6.在严格模式下不能function中的this就再在是window。
(1)在严格模式下不能使用没有var的变量。
<script>
"use strict"
var a =100;
</script>
复制代码
这样使用是错误的。
(2)在严格模式下不能8进制的数字。
<script>
"use strict"
var a =01;
</script>
复制代码
不能这样定义。
(3)在严格模式下不能把函数定义在if语句中。
<script>
"use strict"
if(true){
function f(){
console.log("f...")
}
}
f();
</script>
复制代码
错误用法
(4)在严格模式下函数不能有重名的形参。
<script>
"use strict"
function f(a,a){
console.log("f...")
}
f(a,a);
</script>
复制代码
这样是错误的。
(5)在严格模式下arguments不再跟踪形参的变化。
<script>
"use strict"
function f(a,b){
console.log(a,b)
console.log(argument[0],argument[1])
argument[0] = 10000;
argument[1] = 1000;
console.log(a,b)
console.log(argument[0],argument[1])
}
f(1,2);
</script>
复制代码
输出的结果是:
1 2
1 2
1 2
10000 1000
(6)在严格模式下不能function中的this就不再在是window了。
<script>
"use strict"
function f(){
console.log(this)
}
f();
</script>
复制代码
启动严格模式:
"use strict"
我们上面的写的代码,表示在整个代码段中启动严格模式,还可以在一个函数中启动严格模式:
<script>
b = 200;
function f(){
"use strict"
a = 100
console.log(this)
}
f();
</script>
复制代码
b 变量有效而a变量会报错