ES6知识学习总结

ES6的兼容性

  • IE10+
  • Chrome
  • Firefox
  • 移动端
  • Node.js

ES6的新特性

  • 变量
  • 箭头函数
  • 函数的参数
  • 数组
  • 字符串
  • 面向对象
  • Promise
  • generator
  • 模块化

1.变量(新增let、const)

  • let声明的是变量,const声明的是常量,const修改值会报错,const保存的是内存地址,可以给对象或数组添加属性或元素,但是不能重新复写
  • let、const声明的变量仅在块级作用域内有效,var 声明变量是全局的,没有块级作用域功能
  • let 、const 不存在变量提升 , var 存在变量提升,例如:
console.log(a)
var a = 1;    //先执行var 10,并不会先赋值
  • let 、const不能在同一块级作用域内重复申请
  • let不会进行预处理,var会,例如:
console.log(a)
let a = 1;    //运行之后会报错
console.log(a)
var a = 1;    //运行之后不会报错,只会提示未定义

2.箭头函数(()=>)

例如:

let show = function(){
	alert(123)
}

可以写成

let show=()=>{
	alert(123)
}

(1)只有一个参数的时候,()可以省略。

let show=(a)=>{
    alert(a)
}
show(2)

可以写成

let show=a=>{
    alert(a)
}
show(2)

(2)只有一个return的时候,花括号可以省略。上面可以写成:

let show=a=>alert(a)
show(2)

3.函数的参数

(1)参数的扩展

  • 收集剩余的参数
function show(a,b,...c){
	alert("a="+a",b="+b",c="+c)
}
show(1,2,3,4,5)  //输出a=1,b=2,c=3,4,5

值得一提的是,…c这种扩展只能放在最后面,放在中间不生效。

  • 展开数组
let arr = [1,2,3];
function show(a,b,c){
	alert("a="+a",b="+b",c="+c)
}
show(...arr)   //输出a=1,b=2,c=3

展开后的效果,跟直接把数组的内容写在这一样。

(2)默认参数

function show(a,b=1,c=2){
	alert("a="+a",b="+b",c="+c)
}
show(1,0)  //输出a=1,b=0,c=2

4.解构赋值

  • 左右了两边结构必须一样
  • 右边必须是个东西
  • 声明和赋值不能分开(必须在一句话里完成)
let [a,b,c] = [1,2,3]

5.数组

(1) map() 方法 —— 映射,一个对一个
  • map()方法一定要有一个返回值,没有返回值的话就返回一个undefined
  • map()方法的返回值是一个数组
  • 应用场景:①要返回一个利用原数组经过运算后的数组
let arr1 = [1,2,3]
let arr2 = arr1.map(function(num){
	return num * 2
})
console.log(arr2)   //返回[2,4,6]
  • ②或者在一个对象数组中拿到某一个属性,并返回一个新数组的情况
let persons = [
	{name:"alex",age:18},
	{name:"sky",age:20}
]
let names = persons.map(function(person){
	return person.name
})
console.log(names)   //返回["alex","sky"]
(2) reduce () 方法 —— 一堆出来一个

reduce ( function (a,b,index) { } ) 中有三个参数,a表示每次计算出的结果,再带进去计算的数值,b表示和a计算的数值,index为索引,例如:

计算总和

let arr1 = [1,2,3]
let arr2 = arr1.reduce(function(num,item,index){
    return num + item
})
console.log(arr2)   //输出6

计算平均数

let arr1 = [1,2,3]
let arr2 = arr1.reduce(function(num,item,index){
 if(index != arr1.length - 1){
        return num + item                    
    }else{
        return (num + item)/arr1.length
    }
})
console.log(arr2)

将一个数组中的某些属性值抽出来,组成一个新的数组
在这里插入图片描述
此时输出的是一个数组[“alex”,“sky”,“rose”]

(3) filter () 方法 —— 过滤器

filter()可以返回一个新数组,也可以直接改变原数组

已知对象数组,要把对象数组中一些符合要求的对象重新组成一个数组,例如:

let num1 = [84,12,5,8]
let num2 = num1.filter(function(a){
    if(a%3 == 0){
        return a
    }
})
console.log(num2)  //输出[84,12]

也可以直接写成

let num1 = [84,12,5,8]
let num2 = num1.filter(function(a){
     return a%3 == 0
 })
 console.log(num2)  //输出[84,12]
(4) forEach () 方法 —— 循环
let num1 = [84,12,5,8]
let num2 = num1.forEach(function(item){
    alert(item)
})

也可以加入索引参数:

let num1 = [84,12,5,8]
let num2 = num1.forEach(function(item,index){
    alert(index+ ":" +item)
})
(5) find ()方法
  • 只会找到第一个符合的,找到之后就会直接返回,就算下面还有符合要求的,也不会再找下去

应用场景:

① 在对象数组中,找到符合要求的对象,只能找到第一个符合要求的

let persons = [
	{name:"alex",age:18},
	{name:"sky",age:20}
]
let person = persons.find(function(p){
	return p.name === "alex"
})
console.log(person)   //输出[name:"alex",age:18]

② 两个对象数组,找A数组中有B数组的ID的元素

let coursesType = {id:1,name:"computer course"}
        let courses = [
	        {id:1,name:"java"},
            {id:1,name:"js"},
            {id:2,name:"c++"},
        ]
        let course = courses.find(function(c){
	        return c.id === coursesType.id
        })
        console.log(course)   //输出[id:1,name:"java"]
(6) some() 和 every() 方法
  • some()方法只要有一个满足就行,every()方法要所有满足才可以,即some():一真即真,every():一假即假,跟逻辑运算符差不多

① some只要有一个大于,它就不会再往下找,直接返回true,因为相当于 || (逻辑或运算符)

let computers = [
    {name:"apple",ram:4},
    {name:"IBM",ram:16},
    {name:"Acer",ram:32},  
    {name:"ASUS",ram:64}, 
]
let some = computers.some(function(computer){
    return computer.ram > 16
})
console.log(some)   //输出true

② every()相当于&&,找到第一个错的就直接返回false,不再往下找

let computers = [
    {name:"apple",ram:4},
    {name:"IBM",ram:16},
    {name:"Acer",ram:32},  
    {name:"ASUS",ram:64}, 
]
let every = computers.every(function(computer){
    return computer.ram > 16
})
console.log(every)   //输出false

6.字符串

(1)新增两个方法

① startsWith()

let str = "http://www.baidu.com"
if(str.startsWith("http://")){
    alert("普通网址")
}else{
    alert("其他网址")
}

② endsWith()

let str = "1.txt"
if(str.endsWith(".txt")){
    alert("文本文件")
}else{
    alert("其他")
}

(2) 模板字符串

  • 反单引号(``):连接字符串(${内容}),可以折行
let str1 = "明月"
let str2 = `床前${str1}光`
alert(str2)   //输出床前明月光

7.面向对象

(1) 构造函数

在ES6之前,创建一个实例对象是通过构造函数来实现的

//定义构造函数 Person
function Person(name, age) {
	this.name = name
	this.age = age
}

//在构造函数原型上定义方法 show
Person.prototype.show = function() {
	console.log('姓名:' + this.name)
	console.log('年龄:' + this.age)
}

//创建了一个Person类的实例
var person = new Person('Jack', 18)

console.log(person.name)              // Jack
console.log(person.age)               // 18
person.show()                         /* 姓名:Jack
									     年龄:18      */

我们通过 new 关键字调用构造函数,即可生成一个实例对象。不妨我们再来回顾一下 new 关键字的作用过程,即 var person = new Person('Jack', 18) 等价于以下代码

var person = function (name='Jack', age = 18) {

	// 1.创建一个新的空对象赋值给this
	var this = {}
	
	// 2.执行构造函数里的所有代码
	this.name = name
	this.age = age
	
	// 3.返回this
	return this
}

通过以上代码我们可以得知,构造函数中的 this 指向的是新生成的实例对象

(2) class 语法

使用 class 语法来更改以上实例,看看有什么区别

//用class定义一个类
class Person {
	constructor(name, age) {
		this.name = name
		this.age = age
	}
	show() {
		console.log('姓名:' + this.name)
		console.log('年龄:' + this.age)
	}
}

//生成Person类的一个实例对象person
var person = new Person('Jack', 18)

console.log(person.name)              // Jack
console.log(person.age)               // 18
person.show()                         /* 姓名:Jack
									     年龄:18      */

通过调用实例对象的属性 nameage 以及方法 show,我们可以看到,跟构造函数没有任何的区别,所以说 class 语法就是构造函数的一个语法糖,即构造函数的另一种写法,这两者并无本质区别

其实我们还可以通过 typeof 来验证一下 class 定义的类的类型

class Person {}
console.log(typeof Person)    // function

① constructor

当我们用 class 定义了一个类,然后用关键字 new 调用该类,则会自动调用该类中的 constructor函数,最后生成一个实例对象。constructor函数内部的 this 指向的也是新生成的实例对象。

如果要生成一个不需要任何属性的实例对象,则我们不需要在 constructor 函数里写任何代码,此时可以省略它,例如

class Person {
	//不写constructor函数
	say() {
		console.log('hello world')
	}
}

上述代码省略了 constructor 函数,此时JavaScript会默认生成一个空的 constructor 函数,例如

class Person {
	constructor() {
	
	}
	say() {
		console.log('hello world')
	}
}

以上两段代码是等价的

也正是因为 constructor 函数的存在,class 定义的类必须通过 new 来创建实例对象,否则就会报错

class Person {

}
var person = Person()

/*
报错
var person = Person()
             ^
TypeError: Class constructor Person cannot be invoked without 'new'
*/

而传统的构造函数就可以不通过 new 来调用,因为其本身就是一个函数,若不加关键字 new,则相当于直接执行该函数

② 类方法的定义

在传统的构造函数中,为了使每个实例对象都拥有共同的方法,在构造函数的原型上进行方法的定义,例如

function Person() {}
    Person.prototype.show = function () {
	console.log('hello world')
}

因此,class语法定义的方法也是在原型上的,不过这里称之为类的原型上,同时省略了大量的代码,直接将方法写在 class 内即可

class Person {
	//在Person类的原型上定义了方法 show
	show() {
		console.log('hello world')
	}
	//在Person类的原型上定义了方法 hide
	hide() {
		console.log('bye world')
	}
}

③ get 函数和 set 函数

class类中,可以使用两个内部定义的函数,即 getset,语法为 get/set 属性名() {},分别表示读取属性/设置属性时调用此函数,其中 set 函数接收一个参数,表示所设置的值

class Person {
	get number() {
		return 18
	}
	set number(value) {
		console.log('现在的number值为:' + value)
	}
}

var person = new Person()

//访问属性number
person.number  //   18

//设置属性number为20
person.number = 20  // 打印:现在的number值为:20

当我们访问属性 number 时,会调用 get number() {}函数,故返回 18;当设置属性 number 的值为 20时,会调用 set number() {}函数,故打印了 现在的number值为:20

④ 静态方法(static)

class 类中的方法都是写在原型上的,因此生成的实例对象可以直接调用。现在有一个关键字 static,若写在方法的前面,则表示此方法不会被写在原型上,而只作为该类的一个方法,这样的方法叫做静态方法;相反,若没加关键字 static 的方法就叫做非静态方法

class Person {
	show() {
		console.log('我是非静态方法show')
	}
	static show() {
		console.log('我是静态方法show')
	}
	static hide() {
		console.log('我是静态方法hide')
	}
}

Person.show()    // 我是静态方法show

var person = new Person()

person.show()    // 我是非静态方法show

person.hide()    /*	person.hide()
                           ^
			  TypeError: person.hide is not a function
				
				*/

首先我们直接调用 Person 类的 show 方法,实际调用的就是有关键字 staticshow 方法;

然后我们生成了一个实例对象 person,然后调用 person 实例对象上的 show 方法,实际调用的就是没有关键字 staticshow 方法,从这我们可以看出,静态方法和非静态方法可以重名

最后我们调用了 person 实例对象上的 hide 方法,但报错了,因为在 class 类中,我们定义的是静态方法,即有关键字 statichide 方法,也就是此方法没有被写进类的原型中,因而实例对象 person 无法调用此方法。

我们都知道,类中定义的方法内的 this 指向的是实例对象,但在静态方法中的 this 指向的是类对象

class Person {
	constructor() {
		this.name = 'Lpyexplore'
	}
	show() {
		console.log(this.name)
	}
	static cite() {
		this.show()
	}
	static show() {
		console.log('我是非静态方法show')
	}
}

Person.cite()     // 我是非静态方法show

var person = new Person()

person.show()     // Lpyexplore

首先我们直接调用 Person类的静态方法 cite,执行代码 this.show(),因为静态方法中的 this指向 Person类,所以其实调用的就是静态方法 show,所以打印了 我是非静态方法show

然后我们生成了一个实例对象 person,调用 personshow方法,因为在非静态方法 show中,this指向的是实例对象 person,因此打印了 Lpyexplore

⑤ 实例属性的简易写法

原先我们为实例对象定义的属性都是写在 constructor函数中的

class Person {
	constructor() {
		this.name = 'Lpyexplore'
		this.age = 18
	}
	show() {
		console.log('hello world')
	}
}

var person = new Person()

console.log(person.name)        // Lpyexplore
console.log(person.age)         // 18

现在我们用实例对象的属性新写法来改写以上代码

class Person {
	name = 'Lpyexplore'
	age = 18
	show() {
		console.log('hello world')
	}
}

var person = new Person()

console.log(person.name)        // Lpyexplore
console.log(person.age)         // 18

这种写法就是将 constructor 函数中的属性定义放到了外部,同时不需要写 this,因为此时的属性定义与其他方法也处于同一个层级。

虽然这样的写法比较简便,但也有一定的缺点,那就是用这种写法定义的属性是写死的。

⑥ 静态属性

静态属性就只属于 class 类的属性,而不会被实例对象访问到的属性。

class Person {
	name = '我是实例对象的name属性'
	static name = '我是Person类的name属性'
	static age = 18
}

console.log(Person.name)   // 我是Person类的name属性

var person = new Person()

console.log(person.name)   // 我是实例对象的name属性

console.log(person.age)    // undefined
(3) class 的继承

① 继承的概念

继承就是使一个类获得另一个类的属性方法

② ES5 中原型链实现继承

通过原型链实现继承

// 创建构造函数 Parent
function Parent() {
	// 定义了实例对象属性 name1
	this.name1 = 'parent'
}

// 为 Parent原型定义方法 show1
Parent.prototype.show1 = function() {
	console.log('我是Parent的show1方法')
}

// 创建构造函数 Child
function Child() {
	this.name2 = 'child'
}

// 将构造函数 Child的原型设置成 Parent的实例对象
Child.prototype = new Parent()

// 为Child原型定义方法 show2
Child.prototype.show2 = function() {
	console.log('我是Child的show2方法')
}

// 生成实例对象 child
var child = new Child()

console.log(child.name1)          // parent
console.log(child.name2)          // child
child.show1()                     // 我是Parent的show1方法
child.show2()                     // 我是Child的show2方法

我们可以看到,我们通过改变构造函数 Child的原型 prototype为构造函数 Parent生成的实例对象,实现了继承,即通过构造函数 Child生成的实例对象具有 Parent中定义的属性name1和方法show1,同时也具有属于自己的属性name2和方法show2

③ ES6 中 class 实现继承

ES5中实现继承的写法显然有些麻烦,所以在 class类中,我们可以通过关键字 extends来实现继承

class Parent{
    constructor() {
        this.name1 = 'parent'
    }
    show1() {
        console.log('我是Parent的show1方法')
    }
}

// Child类 继承 Parent类
class Child extends Parent{
    constructor() {
        super();
        this.name2 = 'child'
    }
    show2() {
        console.log('我是Child的show2方法')
    }
}

var child = new Child()

console.log(child.name1)          // parent
console.log(child.name2)          // child
child.show1()                     // 我是Parent的show1方法
child.show2()                     // 我是Child的show2方法

接下来我们详细讲一下super关键字

④ super

在ES6中规定了,在子类继承了父类以后,必须先在子类的 constructor函数中调用 super函数,其表示的就是父级的 constructor函数,作用就是为子类生成 this对象,将父类的属性和方法赋值到子类的 this上。因此,若没有调用 super函数,则子类无法获取到 this对象,紧接着就会报错

class A{
    constructor() {
        this.name1 = 'A'
    }
}

class B extends A{
    constructor() {
        this.name2 = 'B'
    }
}

var b = new B()

/*
        this.name2 = 'B'
        ^
ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor

*/

再看一个例子

class Father{
   constructor(name,age){
        this.name = name
        this.age = age
    }
}

//继承
class Son extends Father{
    constructor(name,age,sex){
        super(name,age,sex)   //相当于先调用的父类的构造函数一遍
        this.sex = sex
        this.color = "黄色"
    }
} 

//实例化
let father = new Father("sky",38)
let son = new Son("alex",18,"男")

console.log(father)
console.log(son)

输出结果
在这里插入图片描述
super()代表的是父类的构造函数,其实 super还可以作为对象使用,即不作为函数调用。当 super子类的普通方法内时,指向的是父类的原型对象;在子类的静态方法内时,指向的是父类

class A{
	show1() {
		console.log('我是A类的show1方法')
	}
}

class B extends A{
	constructor() {
		super()
	}
	show2() {
		super.show1()
	}	
}

var b = new B()

b.show2()              // 我是A类的show1方法

上述代码,B类继承 A类,其中 A类有一个 show1方法,是写在其原型 A.prototype上的,而在 B类的 show2方法中调用了 super.show1(),我们说过 super在普通的方法中指向的是父类的原型对象,所以 super.show1() 相当于 A.prototype.show1()

我们再来看一个 super在子类的静态方法中的例子

class A{
    static hide1() {
        console.log('我是A类的hide1方法')
    }
}

class B extends A{
    constructor() {
        super()
    }
    static hide2() {
        super.hide1()
    }
}

B.hide2()                     // 我是A类的hide1方法

上述代码,B类继承 A类,B类在其静态方法 hide2中调用了 super.hide1(),因为 super在静态方法中指向的是父类,所以 super.hide1() 就相当于 A.hide1()

说到静态方法,其实类的继承,也是可以继承静态方法的

class A{
	static show() {
		console.log('我是A类的show方法')
	}
}

class B extends A{}

B.show()      // 我是A类的show方法

还需要注意的是,当我们在子类的普通方法中通过 super调用父类的方法时,方法中的 this指向的是当前子类的实例对象

class A {
    constructor() {
        this.name = 'Jack'
    }
    show1() {
        console.log(this.name)
    }
}

class B extends A{
    constructor() {
        super();
        this.name = 'Lpyexplore'
    }
    show2() {
        super.show1()
    }
}

var b = new B()

b.show2()                 // Lpyexplore

那么,当我们在子类的静态方法中通过 super调用父类的方法时,方法中的 this指向的是子类,而不是子类的实例对象

class A {
    constructor() {
        this.x = 1
    }
    static show1() {
        console.log(this.x)
    }
}

class B extends A{
    constructor() {
        super();
        this.x = 2
    }
    static show2() {
        super.show1()
    }
}

B.show2()                 // undefined

B.x = 3
B.show2()                 // 3

上述代码中,我们在 B类的静态方法 show2中通过 super调用了 A类的静态方法 show1,执行代码 console.log(this.x),此时的 this指向的是 B类,但因为 B类的 constructor函数中定义的属性 x是定义在 B类的实例对象上的,所以 this.x 返回的是 undefined

所以我们在 B类上定义一个属性 x并且值为 3,此时再此调用 B.show2(),返回的就是 3了。
原文

8. json

(1) json 对象

① JSON.parse()

从一个字符串中解析出json对象

let str = '{"name":"alex","age":18}'

let obj = JSON.parse(str)

console.log(obj)   //输出{name:"alex",age:18}

注意:单引号写在{}外,每个属性名都必须用双引号,否则会抛出异常。

② JSON.stringify()

于从一个对象解析出字符串

let obj = {name:"alex",age:18}

let str = JSON.stringify(obj)

 console.log(str)    //输出'{"name":"alex","age":18}'
(2) json 的简写

① 属性和属性值一样

以前的写法

let a = 1
let b = 2

let json = {a:a,b:b,c:3}

console.log(json) //输出{a:1,b:2,c:3}

现在可以只写一个

let a = 1
let b = 2

let json = {a,b,c:3}

console.log(json) //输出{a:1,b:2,c:3}

② 函数

以前的写法

let json = {
    a:1,
    show:function(){
        console.log(this.a)
    }
}
json.show()

现在的写法

let json = {
    a:1,
    show(){
        console.log(this.a)
    }
}
json.show()

9. Promise

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值