es6是 JavaScript 语言的下一代标准,已经在 2015 年 6 月正式发布了。它的目标,是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。
1.let关键字定义变量
var 关键字定义变量的时候,全局变量和局部变量
let 关键字定义变量的时候,全局的变量和局部变量,块级变量
var a = 10; let b = 20 // 全局变量
;(function (){
var a = 20; let b = 30 //局部变量
}())
if (1<2) {
let b = 30 // 块级作用域
console.log(b); //30
}
console.log(a,b); //10 20
// 用法
for(var i = 0;i<5;i++){
console.log(1,i); // 0 1 2 3 4
setTimeout(function(){
console.log(2,i); // 5 5 5 5 5
},1000)
}
// 使用let解决
for(let i = 0;i<5;i++){
console.log(1,i); // 0 1 2 3 4
setTimeout(function(){
console.log(2,i); // 0 1 2 3 4
},1000)
}
// 使用闭包解决
function outer(x){
return function(){
console.log(4,x);
}
}
for(var i = 0;i<5;i++){
console.log(5,i);//0 1 2 3 4
setTimeout(outer(i),1000)//0 1 2 3 4
}
var count = 3;var count = 3;//没问题
let c = 3;//let c = 3; //报错 c已经定义过了
// let 和 var
// let:不允许在相同的作用于下声明相同的变量,var可以
// let:除了全局变量和局部变量还可以定义块级变量
2.const 定义变量是一个常量,常量不允许修改的
// const 定义变量是一个常量,常量不允许修改的
const c = 3
c = 5
console.log(c); //修改直接报错
const b ;
console.log(b); //必须赋给初始值,不然直接报错
// const 适用的场合
// 一般使用在循环数组里面或者循环对象里面,只对数组或者对象里面的数据进行查询
// 对于引用类型使用const,只对数组进行增删改查不会出现报错,如果修改了引用类型的地址就会报错
const arr = [1,2,3]
arr.push(4)
console.log(arr);//[1,2,3,4]
arr = []
console.log(arr);//报错
const obj = {
name:123
}
obj["name"] = "456"
console.log(obj);// { name: '456' }
obj = {}
console.log(obj);//报错
3.模板字符串
es6模板字符串常用在html字符串拼接的地方
var year = 2021
var month = 11
var day = 24
console.log(year+"-"+month+"-"+day); //2021-11-24 常规字符串拼接
console.log(`${year}-${month}-${day}`);2021-11-24 es6字符串拼接
4.箭头函数和普通函数的定义方式
// 传统函数定义方式
function f1(){
console.log(this);
}
f1() // global 在浏览器是window
console.log(f2);//undefind 变量提升只提升了声明部分
console.log(f2());//报错 f2() 不是一个函数
var f2 = function (){} //函数表达式
// 立即执行函数
;(function(){
console.log("66");
})
// 通过 new Function方式创建函数
var f3 = new Function("var a = 1;var b = 2;var c = a + b;console.log(c)")
f3() //3
// 箭头函数也是属于匿名函数的一种写法
var c = ()=>{}
console.log(this); // {} 在浏览器打印时是window
this.name = "张三"
console.log(this);//{ name: '张三' }
setTimeout(() => {
console.log(this);// 指向上下文,结果为 { name: '张三' }
}, 100);
setTimeout(function(){
console.log(this);//Timeout对象
},100)
var D = (count)=>{
return ++count
}
var D = count=> ++count //方法体只有一句话,有返回值时,可以把return和{} 去掉,如果参数只有一个,可以把参数的()去掉
console.log(D(10));//11
var obj = {
name:"李四",
eat(){
console.log(this.name);
},
eat1:function(){
console.log(this.name);
},
drink:()=>{
console.log(this.name);// 保留与对象obj对象上下文的对象
}
}
obj.eat() //李四
obj.eat1() //李四
obj.drink() // 张三
5.默认参数
function add(a,b){
console.log(a+b);
}
add() //NaN
add(3)//NaN
add(1,2)//3
// 带默认值函数定义的时候,建议把默认值参数写在最后一个参数上面
// 如果调用的时候传递参数,默认值参数就是传递的值
function add2(a,b=4){
console.log(a+b);
}
add2(1)//5
add2(1,7)//8
function add3(){
var sum = 0
for(var i = 0;i<arguments.length;i++){
sum += arguments[i]
// arguments.callee() 自调用
}
console.log(sum);
}
add3(1,2,3,4) //10
// es6获取参数列表的方式
function add4(...array){
console.log(array);
}
add4(3,4)//[ 3, 4 ]
6.对象和数组的遍历
var arr = [1,2,3]
var obj ={
name:123,
age:456
}
// es6提供专门遍历数组的for...of
for (const index of arr) {
console.log(index); //1 2 3
}
// es6提供专门遍历对象的for...in
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
const element = obj[key];
console.log(element);//123 456
}
}
// for...of.. 遍历对象
for(const iterator of Object.entries(obj)){
console.log(iterator);//[ 'name', 123 ] [ 'age', 456 ]
}
for(const iterator of Object.values(obj)){
console.log(iterator);//123 456
}
for(const iterator of Object.keys(obj)){
console.log(iterator);// name age
}
// for..in..遍历数组
for (const key in arr) {
console.log(key);// 0 1 2
}
7.对象字面量创建
// 创建对象的方式
var date = new Date()
// 字面量创建对象
var obj = {
name:"111"
}
var name = "张三"
var age = 10
// es6之前写对象属性的时候,对象的属性添加双引号
var zhangsan = {
"name":name,
"age":age,
"sex":"男"
}
// es6对对象的属性在声明时候进行优化,把双引号去掉了
zhangsan = {
name:name,
age:age,
sex:"男"
}
console.log(zhangsan);//{ name: '张三', age: 10, sex: '男' }
// es6添加对象属性的时候,如果对象属性和字段一样,可以简写
zhangsan ={
name,
age,
sex:"男"
}
var sex = '男'
zhangsan = {name,age,sex}
console.log(zhangsan);//{ name: '张三', age: 10, sex: '男' }
zhangsan = [name,age,sex]
console.log(zhangsan);//[ '张三', 10, '男' ]
8.class类的使用
// es6之前创建类的方式,构造函数
function People(name){
this.name=name
}
// 添加一些方法
People.prototype.work = function(){
console.log("我只想挣钱养家,你却想要我命");
}
// 实现构造函数继承:属性继承,原型上的继承
function Student(name,id){
People.call(this,name)//属性继承
this.id = id
}
// 原型上的继承
Student.prototype = Object.create(People.prototype)
Student.prototype.constructor = Student
var s1 = new Student("zz",10)
console.log(s1.name,s1.id); //zz 10
s1.work() //我只想挣钱养家,你却想要我命
class Father{
// 构造函数
constructor(name){
this.name = name
}
eat(){
console.log(this.name + "ssss");
}
}
class Son extends Father{
constructor(name,id){
super(name)
this.id = id
}
}
var s1 = new Son("你好",10)
console.log(s1.name,s1.id); // 你好 10
s1.eat() // 你好ssss
9.Symbol
symbol 是es6新增的一个基本数据类型,表示数据和数据类型是一个唯一的值,最大的用法使用在对象的属性或者值上面,还可以用定义常量上面。
基本数据类型 string number boolean NaN undefined null symbol,存储在栈空间里面,存的是值本身
引用数据类型 function object array 等引用类型,存储在堆空间,存储的是对象的引用的地址
var s1 = Symbol() //定义一个symbol类型的数据
var s2 = Symbol()
console.log(s1,s2);//Symbol() Symbol()
console.log(s1===s2); //false
console.log(s1==s2); //false
console.log(s1=s2); //Symbol()
var s3 = Symbol("red")
var s4 = Symbol("green")
console.log(s3,s4);//Symbol(red) Symbol(green)
console.log(s3==s4);//false
let s5 = Symbol()
let s6 = Symbol()
var obj = {
name:"小李子",
[s5]:30
}
obj[s6] = "男"
console.log(obj);//{ name: '小李子', [Symbol()]: 30, [Symbol()]: '男' }
console.log(obj["name"]);//动态获取属性 小李子
console.log(obj.name);//静态获取属性 小李子
console.log(obj[s5]);//30
console.log(obj[s6]);//男
// 不能直接使用for..in..进行对对象属性为symbol类型进行遍历
for (const key in obj) {
console.log(key); // name symbol属性用for..in 遍历不出来
}
var arr = Object.getOwnPropertySymbols(obj) //获取symbol类型的字段
for (const iterator of arr) {
console.log(iterator); //Symbol() Symbol()
}
// symbol 使用常量上面
const COLOR_RED = Symbol("red")
// 使用单例方式创建symbol类型
var s9 = Symbol.for("red")
var s10 = Symbol.for("red")
console.log(s9==s10); //true
console.log(Symbol.keyFor(s9));//取值 red
10.关于对象和数组的解构
var arr = [1,2,3]
console.log(arr[1]); //2
// es6新增数组解构,把数组的每一个元素解构成一个变量
let [c1,c2,c3] = arr
console.log(c1,c2,c3);// 1 2 3
console.log(...arr); // 1 2 3
let [c4,c5,...c6] =arr
// 可以把所有的数组元素写在一个数组里面,必须使用展开的运算符...
console.log(c4,c5);//1, 2,[ 3 ]
// 数组的组合
var arr2 = [4,5,6]
// arr2.forEach(function(v){
// arr.push(v)
// })
// console.log(arr);//[ 1, 2, 3, 4, 5, 6 ]
arr = arr.concat(arr2)
console.log(arr);//[ 1, 2, 3, 4, 5, 6 ]
// 使用...进行数组赋值
// arr.push(...arr2)
// console.log(arr);//[ 1, 2, 3, 4, 5, 6 ]
arr = [...arr,...arr2,7,8,9]
console.log(arr); //[1, 2, 3, 4, 5, 6, 7, 8, 9]
var obj = {
name:"zhangsan",
age:10,
sex:"男"
}
// 对象的解构,要求解构出来的变量名字和对象属性名字必须一致,这个就是按需加载
let {name,age} = obj
console.log(name,age);//zhangsan 10
var people = {
width:200,
height:200,
...obj
}
console.log(people);//{ width: 200, height: 200, name: 'zhangsan', age: 10, sex: '男' }
// assgin keys values entries 都是属性es6的api
var newObj = Object.assign(people,obj)
console.log(newObj);//{ width: 200, height: 200, name: 'zhangsan', age: 10, sex: '男' }
var string = "ABC"
var [a,b,c] = string
console.log(a,b,c); // A B C
// 数组的解构 : let [c4,c5,...c6] =arr
// 对象的解构 : let {name,age} = obj
// 数组赋值 arr = [...arr,...arr2,7,8,9]
11.map
map:保存的是一些键值对,相当于数据字典,和对象object类型的区别。map的键可以是任意类型的,,但是对象的键只能是字符串类型或者symbol类型。对象数据是无序的,但是map数据四有顺序的。对象的属性的个数只能手动计算,但是map通过size函数获取大小。对象都有自己的原型,对象自己的属性和原型上属性有命名冲突的现象。
var map1 = new Map() //创建map对象
// 设置键值对
map1.set(10,'hello')
map1.set("key1","你好")
console.log(map1.size);//2
console.log(map1.get(10)); //获取map1中10的值 hello
console.log(map1.get("key1") ); // 你好
console.log(map1.has("key1"));//判断是否存在key1 true
// map1.clear() //清空map1
// map1.delete(10) //删除对应的键值
// 遍历,不能用for..in
for (const key of map1.keys()) {
console.log(key); //10 key1
}
for (const key of map1.values()) {
console.log(key); //hello 你好
}
for (const key of map1.entries()) {
console.log(key); //[ 10, 'hello' ] [ 'key1', '你好' ] 数组
}
12.set
set数据集:主要是用来存储任意数据类型的唯一值
set主要是用来数组去重的,也可以求一些数组的交集差集并集等
var arr = [1,"a","a"]
var set = new Set()
set.add({name:"zhangsan"})
set.add("hello")
set.add("hello")
set.add(10)
set.add(false)
set.add([1,'a'])
set.add([1,'a'])
console.log(set);//Set(5) { { name: 'zhangsan' }, 'hello', 10, false, [ 1, 'a' ], [ 1, 'a' ] } 数组的地址不同所以不会去重,但字符串相同的就会去重
// for..of可以直接遍历set
for (const iterator of set) {
console.log(iterator);//{ name: 'zhangsan' } hello 10 false [ 1, 'a' ]
}
// 创建set对象
var set2 = new Set(arr)
console.log(set2);//Set(2) { 1, 'a' } 去重了,把数组变成对象了
var arr1 = [...set2] //把对象解构再转成数组,实现数组去重
console.log(arr1);//[ 1, 'a' ]
// 交集
var set3 = new Set()
set3.add(3)
set3.add(4)
set3.add(5)
var set4 = new Set()
set4.add(4)
set4.add(5)
set4.add(6)
var arr2 = [...set3].filter(x=>{
return set4.has(x) // 判断set4是否存在下,存在就过滤出来
})
console.log(arr2);//[ 4, 5 ]
// 差集
var arr3 = [...set3,...set4].filter(x=>arr2.indexOf(x)===-1)
console.log(arr3);//[ 3, 6 ]
// 并集
var arr4 = [...set3,...set4]
var set5 = new Set(arr4)
console.log([...set5]); //[ 3, 4, 5, 6 ]
13.proxy
//
var obj = {
name:"张三"
}
// 属性描述 属性拦截作用
Object.defineProperty(obj,"height",{
//value:190,//默认值
configurable:true,//允许删除
//writable:true, //允许修改
enumerable:true,// 允许枚举
// set修改属性值 不能和value,writeable进行连用
set:function(v){
console.log("11");
//obj.height = v//不能这样写,会导致递归调用
if (v>300) {
height = v
}else{
throw Error("错误")//抛出异常
}*
},
// get获取属性值
get:function(){
// 获取属性值
console.log("222");
return height
}
})
// delete obj.name
// delete obj.height
// obj.name = "李四"
obj.height = '310'
console.log(obj.height);
// for (const key in obj) {
// console.log(key+'='+obj[key]); //name=张三 height=190
// }
// 属性代理:不是直接操作对象本身,通过操作代理对象进行属性的修改或者扩充
var obj = {
s1:"001",
name:"张三",
age:10
}
// 代理对象
var handleObj = {
// target 就是元素对象obj
get(target,key){
// 获取name属性
if (key=="name") {
return target[key]+'s1'
}
// 获取age属性
if (key=='age') {
return target[key]+'s2'
}
},
set(target,key,value){
if (value>200) {
throw "你活够了"
}
target[key] = value + 10
}
}
// 创建代理对象,使用obj和代理对象产生关联
var proxy = new Proxy(obj,handleObj)
proxy.age = 200 //修改obj的age属性
proxy.name = 'ss'
console.log(proxy.name);//ss10s1
console.log(proxy.age);//210s2
console.log(obj.age);
// 通过创建出来的proxy代理对象操作原始对象obj的属性,通过handleObj进行属性的拦截