ES2015

关于ES2015,ECMAScript也是一个脚本语言,JavaScript是ECMAScript的扩展
因为ES2015 变化比较大,所以我单独记一下

let

es2015之前有俩种作用域,全局作用域和函数作用域,es2015新增了块级作用域

if(true){
	var a = '111'
}
console.log(a)//  111
function fn(){
	let b = '111'
}
console.log(b)//b is not defined
//在块级作用域中声明的变量只能在块级作用域中使用
for(var i=0;i<3;i++){
	for(var i=0;i<3;i++){
		console.log(i)//0 1 2
	}
	console.log('内部结束 i='+i)//内部结束 i=3
}
for(let i=0;i<3;i++){
	for(let i=0;i<3;i++){
		console.log(i)//0 1 2 0 1 2 0 1 2
	}
	console.log('内部结束 i='+i)//内部结束 i=3
}
//虽然let对同名的计数器这里指(i)有处理,但是不建议使用同名的计数器。
var elements= [{},{},{}]
for(var a=0;a<elements.length;a++){
    elements[a].onclick=function(){	
        console.log(a)
    }
}
elements[0].onclick()//3
//当然之前可以通过闭包的方式去解决这种问题
for(var a=0;a<elements.length;a++){
    elements[a].onclick=(function(a){	
	    return function(){
	    console.log(a)
	    }
    })(a)
}
elements[0].onclick()//0
//有了块级作用域就不用这么麻烦了
for(let a=0;a<elements.length;a++){
    elements[a].onclick=function(){	
        console.log(a)
    }
}
elements[0].onclick()//0
//内部其实也是闭包的机制
console.log(foo)//undefined
var foo = 'hhh'
console.log(foo)//Cannot access 'foo' before initialization
let foo = 'hhh'
//引用错误 说明了let定义的变量不会提升到代码一开始执行的位置

const

在let的基础上增加一个只读的特性,声明过后不允许再被修改

const name = 'swh'
name ='smg'
//报错 Assignment to constant variable.
const name
name='swh'
//报错 Missing initializer in const declaration
 const常量说明在声明的时候就必须给赋值。不能像let一样声明和赋值放到俩个语句中
 const obj = {
 }
 obj.name = 'swh'
 obj = {}//报错
 const不能被修改只是说在声明了之后不能在指向一个新的内存地址,并不是说不允许修改恒量中的属性成员
 尽量不用var 默认使用const 

数组的解构

从数组获取指定元素的语法
	//以前我们需要通过数组的索引来找到对应的值
	const arr =['a','b','c']
	const a = arr[0]
	const b = arr[1]
	const c = arr[2]
	console.log(a,b,c)//a b c
	//解构语法,声明一个方括号,里面是我们要提取的变量名,需要一一对应,会按照变量名顺序分配指定的数据
	const [a,,c] = arr
	console.log(c)//c
	//除此之外还可以从解构位置变量名之前添加...表示从当前位置开始往后的所有成员,只能在最后一个位置使用
	const [foo,...abc] =arr
	console.log(abc)//b c
	//当解构的数量个数小于被解构的数组长度,就会从前到后去提取。反之为undefined
	const [foo] =arr
	console.log(foo)//a
	//还可以给解构对象设置默认值,如果没有取到就返回默认值
	const [foo,b,c,d='d'] =arr
	console.log(d)//d

对象的解构

对象的解构需要根据属性名来提取
	// 解构的方法就是在以前变量的位置加一个{}
	//这里变量名 去匹配被解构对象中的成员,去提取成员中的值
	const obj = {name:'ssw',age:18}
	const {name} = obj
	console.log(name)//ssw
	//如果当前作用域中有相同的变量属性就会发生冲突
	const name = 'hhh'
	const {name} = obj
	console.log(name)//报错 Identifier 'name' has already been declared
	//利用重命名的方式去解决这种冲突,冒号后面的重命名之后加等号可添加默认值
	const name = 'hhh'
	const {name:objname='rtyuio'} = obj
	console.log(objname)//ssw
	//示例 解构console对象方法
	const {log} = console
	log('foo')//foo
	log('fo')//fo
	log('f')//f

模板字符串 字面量

传统定义字符串的方式是通过单引号''
ES2015中推出了模板字符串``这种定义方式
	const str = 'hello,my name swh'
	const str = `hello,my name swh`
	console.log(str)
	//可直接在字符串中使用换行符,对于我们输出HTML字符串是非常方便的
	const str = `hello,my
	 name swh`
	console.log(str)
	//利用插值表达式的方式在字符串中插入所需要的数值
	const name ='swh'
	const str = `hello,my name ${name}`
	console.log(str)
	//插值表达式里面是纯js运算语法,所以可以这样
	const str = `hello,my name ${12+52}`
	console.log(str)

//进阶用法

// const hello = console.log `aaa hhh ccc`// 带标签的模板字符串,这个标签是一个特殊的函数,添加这个标签就是调用这个函数
const name = 'swh'
const genter = true
function mytagfunc(array,name,genter){//这个函数可以接收到一个数组参数(array),还有所有这个模板字符串中出现的表达式的返回值(name,genter)
    console.log(array,name,genter)
    // return '1221'
    const sex = genter?'man':'woman'
    return 	array[0]+name+array[1]+sex+array[2]
 }
	const fn = mytagfunc  `hey my name is ${name} is a ${genter}.`
	console.log(fn)
	//可以对我们的模板字符串进行加工,使代码跟可读

字符串 扩展方法

const str = `Error: foo hhh is a man.`
console.log(str.startsWith('foo'))//字符串是否以foo开头
console.log(str.endsWith('.'))//字符串是否以.开头'
console.log(str.includes(`is`))//字符串中是否有is

参数默认值

	//这种参数默认值 只有在没有传参或者参数为undefined是才会有
	// function foo(enable=true){
	//      console.log(enable)
	// }
	// foo()
	//如果有多个参数 默认值要放到最后 否则默认值会失效
	function foo(abc,enable=true){
	    console.log(abc+enable)
	}
	foo('111')

剩余参数

	// function foo(a,b){
	//     console.log(arguments)//以前我们用这个  这个是伪数组
	// }
	foo(1,2,3,4,5,6)
	
	function foo(a,b,...args){//因为接收的是剩余参数,所以只能放到最后,而且只能用一次
	    console.log(args)
	}

展开数组

	const arr = ['foo','tag','man'];
	// console.log(arr)
	//通过下标传,如果是不固定数组长度,这种方法就行不通了
	console.log(
	    arr[0],
	    arr[1],
	    arr[2]
	)
	//以前还会用到apply方法,这种方法可以接收一个数组作为参数
	console.log.apply(console,arr)
	//...会自动把需要的数组里的参数按照次序依次传到函数中
	console.log(...arr)

箭头函数

	 function foo(aa){
	     return aa+1;
	 }
	 const foo=n=>n+1  //单个参数和一句函数体语句时
	const foo=(n,m)=>{//多个参数和多句函数体
	     console.log(m)
	     return n+m
	 }
	 console.log(foo(2))

箭头函数与this

const prosan = {
    name:`aaa`,
    // foo:function(){
    //     console.log(`sss ${this.name}`)
    // }
    foo:()=>{
        console.log(`sss ${this.name}`)
    },
    fooAsync:function(){
        const _this = this
        setTimeout(()=>{
            console.log(this.name)
        },1000)
    }
}
prosan.fooAsync()
//箭头函数中没有this的机制  箭头函数不会改变this的指向 所以箭头函数外this指向什么里面就指向什么

对象字面量增强

const bar = '4444'
const obj ={
    foo:'2112',
    // bar:bar
    bar,//如果要添加的属性名和变量名一致的话可以省略成这样
    // fn:function(){
    //     console.log(foo)
    // }
    //这里定义函数可以省略掉冒号和function  这种方法是普通的函数,也就是说如果通过对象去调用这个方法,那么内部的this就会指向这个对象
    fn(){
        console.log(`${this.foo}`)
        console.log(this)
    },
    //计算属性名  可以将属性名替换成任意的表达式。用[]包起来,表达式的执行结果作为属性的属性名
    [1*5]:'21231'
}
console.log(obj)
obj.fn()

对象扩展方法

		Object.assign   源对象覆盖目标对象中的值
//Object.assign  方法 第一个参数是目标对象,也就是最后需要的对象,后面的参数是源对象,也就是需要取里面的值去覆盖目标对象里的值
// const obj1={
//     a:'111',
//     b:'222'
// }
// const obj2 ={
//     a:'333',
//     c:'444'
// }
// const obj3 ={
//     a:'666',
//     d:'888'
// }
// console.log(Object.assign(obj2,obj1,obj3))

function fn(obj){
    // obj.name = '11111111111'
    const needobj = Object.assign({},obj)
    needobj.name ='111111'
    console.log(needobj)

}
const obj ={name:'2222222'}
fn(obj)
console.log(obj)

对象扩展方法

		Object.is 判断俩个值是否相等
console.log(
	//之前我们可以使用俩个等号的相等运算符
	//会在比较之前自动转换数据类型
	0==false//true
	//还有 三个等号的严格相等运算符
	0===false//false
	//严格三等运算符,区分不了正零和负零,NaN也不相等,当然这正零负零开发中我是用不到
	+0===-0//true
	NaN===NaN//false,其实俩个NaN应该是相等的
	Object.is(+0,-0)//可以区分正零负零
	Object.is(NaN,NaN)//NaN也是相等的
)

proxy

在ES5中如果我们要监视一个对象属性的读写,我们需要用到Object.defineProperty()方法,在ES2015中提供了新的方法,Proxy相比于Object.defineProperty()更加的强大。

const person = {
    name:'swh',
    sex:'男'
}
const personProxy = new Proxy(person,{
    get(target,property){//通过get方法来监视属性的访问,接收俩个参数,第一个是代理的目标对象,第二个是外部所访问的属性名
        // console.log(target,property)
        return property in target?target[property]:'default'
    },
    set(target,property,value){//set方法去监视设置属性的过程,接收三个参数,写入的代理对象,写入的属性名称,写入的属性值
        // console.log(target,property,value)
        // 可以做一些校验
        if(property==='age'){
            if(!Number.isInteger(value)){
                throw Error(`${value} is not an int`)
            }
        }
        target[property] = value
    },
});//通过new的方式创建一个代理对象,proxy的第一个参数就是我们需要代理的目标对象
//第二个参数也是一个对象,这个对象我们可以看成是代理的处理对象
// personProxy.age = 'a'
personProxy.age = 23
console.log(personProxy.name)
console.log(personProxy.age)

proxy VS Object.defineProperty()

Object.defineProperty()只能监视到对象的读写,而proxy能够监视到更多操作例如 delete方法等等

const person = {
   name:'swh',
   age:20
}
const pensonProxy = new Proxy(person,{
   deleteProperty(target,property){
       console.log(target,property)
       delete target[property]
   }
})
delete pensonProxy.age
console.log(person)

Proxy更好的支持对数组对象的操作

const list = [];
const pensonProxy = new Proxy(list,{
   set(target,property,value){
       console.log(property,value);
       target[property] = value
       return true //表示写入成功
   }
})
pensonProxy.push(111)
pensonProxy.push(222)

proxy 是以非侵入的方式 监管了对象的读写,意思是一个已经定义好的对象,我们不需要对对象进行操作就能监管到对象的读写
Object.defineProperty()要求我们单独定义被监管的属性。

class 类

// 在ES2015之前 都是通过定义函数以及函数的原型对象来实现的类型

// function Person(name){
//     this.name = name
// }
// Person.prototype.say=function(){
//     console.log(this.name)
// }
//class 实现以上类型
class Person {
   constructor(name){
       this.name = name
   }
   say () {
       console.log(`my name is ${this.name}`)
   }
}
const p =new Person('swh')
p.say()

static 静态方法

// 实例方法  需要通过这个类型构造的实例对象去调用 
// 静态方法  直接通过这个类型本身去调用
// ES2015中新增的静态方法 static
class Person {
    constructor(name){
        this.name = name
    }
    say () {
        console.log(`my name is ${this.name}`)
    }
    static create(name){
        return new Person(name)
    }
}
const a = Person.create('swh')
a.say()
//由于静态方法是挂载到类型上面的,所以静态方法内部this指向的是当前的类

extends 类的继承

// ES2015之前多数情况会使用原型对象继承
class Person {
    constructor(name){
        this.name = name
    }
    say () {
        console.log(`my name is ${this.name}`)
    }
}
class Student extends Person{
    constructor(name,number){
        super(name)//父类  这里指Person类
        this.number = number
    }
    hello(){
        // super.say()
        console.log(`my scholl number is ${this.number}`)
    }
}
const hhh = new Student('swh','123')
hhh.say()
hhh.hello()

set

全新数据结构,是一个集合 set里面的成员不允许重复

const set = new Set()
set.add(1).add(2).add(3).add(4).add(2)//重复添加会忽略
// console.log(set)
//可以利用循环遍历集合
// set.forEach(i=>console.log(i))
// for(let i of set){
//     console.log(i)
// }
//长度 类似于length
// console.log(set.size)
//has  判断集合中是否存在某个特定的值
// console.log(set.has(3)) 
//delele  删除集合中的某个值
// console.log(set.delete(4))
// console.log(set)
//clear 清除当前集合
// set.clear()
// console.log(set)
//set 为数组中的元素去重
const arr = [5,1,3,4,5,7]
const newarr = new Set(arr)
console.log(newarr)
//可以用 Array.from 方法将set集合转化为数组,也可以通过...的形式在空数组中展开set集合
console.log(Array.from(newarr))
console.log([...newarr])

map

数据结构 键值对集合

const m  = new Map()
const obj = {name:'swh'};
m.set(obj,100)
console.log(m)
console.log(m.get(obj))
m.forEach((value,key)=>{
    console.log(value,key)//值,键
})
console.log(m.has(obj))
console.log(m.delete(obj))
m.clear()
console.log(m)

symbol

每个symbol都是独有的

const obj = {
    [Symbol()]:'1212'
}
console.log(obj)
//因为每个symbol都是独有的 所以可以用来定义私有成员
console.log(Symbol()==Symbol())
const name = Symbol()
const person = {
    [name]:'swh',
    say(){
        console.log(this[name])
    }
}
// 因为我们没有 办法、创建一个完全相同的symbol 
console.log(person[Symbol()])//所以取不到
person.say()//只能通过这个对象的普通名称的成员来调用
//null number undefined string symbol bigint boolean object  
//如果我们要使用一个相同的symbol 可以通过全局变量和symbol提供的静态方法来实现
const a1 = Symbol.for('abc')
const a2 = Symbol.for('abc')
console.log(a1===a2)//相同的字符串返回的一样
//如果传入的不是字符串 会被转成字符串 这个要注意
console.log(Symbol.for(true)===Symbol.for('true'))
/********************************************************* */
const hhh = {
    [Symbol.toStringTag]:'HObject'
}
console.log(hhh.toString())
/*********************************************************** */
const abc = {
    [Symbol()]:'aaaaaaa',
    foo:'bbbbbbbbbbb'
}
for(let a in abc){
    console.log(a)
}
console.log(Object.keys(abc))
console.log(JSON.stringify(abc))
//以上三种都会忽略掉  symbol  
console.log(Object.getOwnPropertySymbols(abc))

for…of

const arr = [100,200,300,400]
for(const item of arr){
    if(item>300){
        break;//可直接使用break终止循环
    }
    console.log(item)
}
/************************************ */
// 遍历 set 数据结构
const abc = new Set(['a','b'])
for(const c of abc){
    console.log(c)
}
//遍历map数据结构
const m = new Map()
m.set('foo','123')
m.set('age','90')
for(const [key,value] of m){//利用数组的结构直接拿到键和值
    console.log(key,value)
}

//迭代器 iterable
// 实现for of的类型中都有一个iterator 方法 也就是迭代器,里面有一个next方法

const obj= {
    arr:['a','c','t','i','o','n'],
    [Symbol.iterator]:function(){
        let index = 0
        const self =this
        return {
            next:function(){
                const result ={
                    value:self.arr[index],
                    done:index>=self.arr.length
                }
                index++
                return result
            }
        }
    }
}
for(const a of obj){
    console.log(a)
}

Generator

// function * foo(){
// 	console.log('aaa')
// 	return 100
// }
// const result = foo()
// console.log(result.next())


function * foo(){
	console.log('aaa')
	yield 100
    console.log('bbb')
	yield 200
    console.log('ccc')
	yield 300
}
const result = foo()
console.log(result.next())
console.log(result.next())
console.log(result.next())
console.log(2**10)

ES2016

const arr = ['11',2,NaN,'sss']
console.log(arr.includes(NaN))//查找数组中是否有指定值,可查NaN
console.loh(2**10)//2的10次方

ES2017

// const obj = {
//   foo: 'value1',
//   bar: 'value2'
// }

// Object.values -----------------------------------------------------------

// console.log(Object.values(obj))

// Object.entries ----------------------------------------------------------

// console.log(Object.entries(obj))

// for (const [key, value] of Object.entries(obj)) {
//   console.log(key, value)
// }

// console.log(new Map(Object.entries(obj)))

// Object.getOwnPropertyDescriptors ----------------------------------------

// const p1 = {
//   firstName: 'Lei',
//   lastName: 'Wang',
//   get fullName () {
//     return this.firstName + ' ' + this.lastName
//   }
// }

// // console.log(p1.fullName)

// // const p2 = Object.assign({}, p1)
// // p2.firstName = 'zce'
// // console.log(p2)

// const descriptors = Object.getOwnPropertyDescriptors(p1)
// // console.log(descriptors)
// const p2 = Object.defineProperties({}, descriptors)
// p2.firstName = 'zce'
// console.log(p2.fullName)

// String.prototype.padStart / String.prototype.padEnd  --------------------

// const books = {
//   html: 5,
//   css: 16,
//   javascript: 128
// }

// // for (const [name, count] of Object.entries(books)) {
// //   console.log(name, count)
// // }

// for (const [name, count] of Object.entries(books)) {
//   console.log(`${name.padEnd(16, '-')}|${count.toString().padStart(3, '0')}`)
// }

// 在函数参数中添加尾逗号  -----------------------------------------------------

// function foo (
//   bar,
//   baz,
// ) {

// }

// const arr = [
//   100,
//   200,
//   300,
// ]
// const arr = [
//   100,
//   200,
//   300,
//   400,
// ]
// const arr = [
//   100,
//   200,
//   300
// ]
// const arr = [
//   100,
//   200,
//   300,
//   400
// ]

未完 Async/await

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值