ES6新特性

一、新增数据类型Symbol。
      概念:

            Symbol代表独一无二的

    Symbol类型的值通过Symbol函数来生成,同时Symbol函数生成的值是唯一的

    Symbol函数何以接收字符串作为参数,但是即使相同参数返回的值也是唯一的

   作用:

    属性私有化

    数据保护

       

//没有参数的情况
let s1 = Symbol();
let s2 = Symbol();

s1 === s2      //false


//有参数的情况
let s1 = Symbol("fun");
let s2 = Symbol("fun");

s1 === s2      //false


let mySymbol = Symbol();
//第一种写法
let a = {};
a[mySymbol] = "Hello!";
//第二种写法
let a = {
     [mySymbol]: "Hello!"  
}
//第三种写法
let a = {};
Object.defineProperty(a,mySymbol,{value: "Hello!"});
//枚举Symbol的key值
Object. getOwnPropertySymbols(obj);
//注意,Symbol作为对象的key值不能被for in进行遍历。

 

二、块级作用域。

  概念:在ES6中,凡事{}包裹的代码都是跨级作用域,凡事在块级作用域中用let、const声明的变量都有一个暂时性死区。

{
    let a = 20;  
}
console.log(a);   //报错

 

三、var、let、const声明变量。

  var

    支持变量声明与解析

    不支持块级作用域

    可以重复声明。

  let

    不支持变量声明与解析

    支持块级作用域

    不可以重复声明

    用let声明的变量或者方法只能在代码块中生效。

{
      let a = 10;
      var b = 20;
}    
console.log(a);     //报错
console.log(b);     //20

  const

    不支持变量声明与解析

    支持块级作用域

    不可以重复声明

    声明变量,一旦声明不可修改

    声明变量必须赋值,不可以像var一样先声明后再定义。  

 

四、解构赋值。

  概念:允许按照一定格式,从对象和数组中提取值。

//数组解构
let [a,b,c] = [1,2,3];
console.log(a,b,c);     //1,2,3

//对象解构,对象解构时key值必须要一一对应。
let {name,age} = {name: "张三",age: 20};
console.log(name,age);    //张三   20

//对象解构+别名
let {name: _name, age: _age} = {name: "张三", age: 20};
console.log(_name,_age);      //张三   20

//多重解构
let {obj:{name},arr:[a,b]} = {obj:{name: "张三"},arr: [10,20]};

 

五、扩展运算符

  概念:将数组或对象转换成参数序列,使用逗号分割的序列。

  作用:

    1、数组、对象的合并

    2、函数剩余参数

    3、替代arguments

//数组合并
let arr1 = [10,20,30];
let arr2 = [40,50,60];
let newArr = [...arr1,...arr2];
console.log(newArr);       //[10,20,30,40,50,60];

//展开数组
console.log(Math.Max(...arr));

//对象合并
let obj1 = {width: 100, height: 100};
let obj2 = {left: 100, top: 100};
let newObj = {...obj1,...obj2};
console.log(newObj); //{width:100,height:100,left:100,top:100};

 

六、字符串模版。

  1、字符串太长需要换行怎么办?

//常规解决办法
var a = "<div>" + 
            "<span>"+num+"</span>"
            "</div>";

//ES6语法
let a = `<div>
             <span>${num}</span>
            </div>`

  2、字符串太长怎么办?

let phone = 15844423232
let intro = `my name is chj, my phone id ${phone}`;

  3、includes字符串搜索。

//ES6神器,includes方法,str.insludes(内容),找到了返回true,没找到返回false

let str = "good method!";
str.includes("method");   //true   

  4、判断首尾,startsWith  endsWith

/*
    startsWith判断是否位于头部
    endsWith判断是否位于尾部
    这两个方法是includes的扩展
*/

let str = "how are you?";
str.startsWith("how");     //true
str.endsWith("?")            //true

  5、repeat字符串重复

//str.repeat(n);     将字符串重复n次
let str = "abc";
str.repeat(3);       //abcabcabc

 

七、对象新增方法。

  1、对象的简写

let a = 10;
let obj = {a};
//等价于
let obj = {a: 10};
//当key值和value值一样的时候我们可以写一个。

  2、Object.is

//判断两个对象是否指向同一个内存地址
let obj1 = {a: 1, b: 2};
let obj2 = obj1;
Object.is(obj1, obj2);   //true

  3、Object.assign

//合并对象
let obj1 = {name: '曹海杰', age: 20};
let obj2 = {sex: '男'};
let newObj = Object.assign(obj1, obj2);   
console.log(newObj);     //{name: '曹海杰', age: 20, sex: '男'};

 

八、数组中新增的方法。

  1、Array.of()

//将一组值转换为数组
let arr = Array.of(1,2,3,4);
console.log(arr);     //[1,2,3,4];

  2、Array.from()

//将伪数组转换为数组。
let aLi = Array.from(document.getElementsByTagName("li"));
console.log(aLi instanceof Array);    //instanceof判断某对象是否属于某类的实例。

  3、Array.find()

//通过条件查找数据,返回第一个符合条件的数据。
let arr = [1,2,3,4];
let n = arr.find(function(item, index, array) {
    return item > 3;
})
console.log(n);   //4

  4、Array.findIndex()

//查找数组中符合条件的数据的下标,如果没有找到则返回undefined
let arr = [1,2,3,4];
let n = arr.findIndex(function(item, index , array) {
     return item > 3; 
})    
console.log(n);

  5、Array.fill();

//对数组进行填充,语法:arr.fill('内容',开始下标,结束下标);
let arr = [1,2,3,4];
arr.fill('qwe', 1, 3);
console.log(arr);       //[1, 'qwe', 'qwe', 4];

 

九、for of   and    for in

/*  
    1、for of 是ES6的,for in 是ES5的
    2、for of 遍历的是值,for in遍历的是键
    3、for of 不能遍历对象,for in 既可以遍历对象也可以遍历数组
    4、for of 遍历数组的时候,如果有未定义的项,遍历出来的是undefined,for in 则遍历不到
    5、for of 不能遍历到原型上定义的属性(自定义属性),for in 可以遍历到
    6、for of 的兼容性不是很好,移动端安卓微信浏览器不支持,Safari支持
*/
Array.prototype.hehe = '呵呵';
let arr = [1,2,3, ,4];
for (let item of arr) {
     console.log(item);      //1,2,3,undefined,4
}

for (let prop in arr) {
     console.log(prop);      //0,1,2,4,hehe  
}

let obj = {
     name: 'chj',
     age: 20
}    

for (let item of obj) {      //报错
     console.log(item);      
}

for (let prop in obj) {
     console.log(prop);      //name age
}    

 

十、函数

  1、函数参数默认值

//ES6之前函数怎么设置默认值
function fn(x) {
     let x= x || 10;  
}

//ES6函数默认值,等价于上面的写法,如果没有传递参数,就使用默认值10

function fn(x=10) {

}

  2、剩余参数

//fn函数中a接收实参1,...rest接收剩余参数为一个数组。
funciton fn(a, ...rest) {
    console.log(...rest);       //[2,3,4,5];
}
fn(1,2,3,4,5);

  3、箭头函数

//语法一  function 换成 () => 
let fn = (a) => {
     console.log(a)
}        

//语法二   不写{}默认表示return,当前函数意思是返回a这个值
let fn = a => a
fn(10);

//语法三   不写{}默认表示return,当前函数表示返回一个对象
let fn = a => ({a:1});

/*
    箭头函数特点:
        1、this指向离自己最近的外层作用域的对象
        2、不能当作构造函数使用(箭头函数是匿名函数,没有函数名字所以没有办法new)
        3、没有arguments这个参数(ES6已经取消arguments这个参数了)
        4、不能当作generator函数
*/

 

十一、Set集合

/*
    Set: 集合
        1、类似于数组,但成员的值是唯一的,没有重复的值,并且是无序的
        2、Set是一个构造函数
        3、Set每次执行完毕后都会返回一个Set,因此可以进行链式调用
*/
let s = new Set();
//添加  add()
s.add("a").add("b");
console.log(s);    //Set(2)  {"a","b"};

//删除  返回值是一个布尔值
s.delete("a") ;   //true

//判断元素是不是Set的成员,返回值是一个布尔值
s.has("a");   //true

//清除所有    没有返回值
s.clear();

//返回所有键名
s.keys();

//返回所有value值
s.values();

//返回所有键值对
s.entries();

//可以通过for of 遍历每一个值
for(let item of s) {
    console.log(s);
}    

 

十二、Map字典类型结构

/*
    1、字典:用来存储不重复key的hash结构,不同于Set集合,字典使用[键,值]的形式来存储
    2、Map执行完毕后都会返回一个Map,可以进行链式调用
    3、特点:普通对象只能通过字符串来当作key值,但是Map可以使用任何值来当作key值
*/
//创建Map对象
let map = new Map({
     ["a", 1],
     ["b", 2]
})   
console.log(map);     //Map(2)   {"a" => 1, "b" => 2}

//获取map长度
map.size

//添加数组
map.set("c",3)

//获取map值
map.get("a")

//删除数据 删除成功返回true
map.delete("a")

//检测map中是否含有某个值  返回布尔值
map.has("a")

//清除所有数据
map.clear();

//获取所有key值
map.keys();

//获取所有value值
map.values();

//获取所有键值对
map.entries();

//遍历map对象     index在前item在后(数组中item在前)
map.forEach((index, item) => {
      console.log(index, item); 
})

 

十三、Proxy介绍

  概念:Proixy是ES6中新增的一个特性。

  作用:在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须想通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写,很类似于设计模式中的代理模式。

  基本用法:

let p = new Proxy(target, handler);

  参数:

    target: 用Proxy包装被代理的对象(可以是任意类型的对象,包括原生数组、函数、甚至是另一个代理)

    handler:是一个对象,其声明了代理target的一些操作,其属性是当执行一个操作时定义代理的行为的函数

  特点:

    1、可以劫持整个对象,并返回一个新对象

    2、有13中劫持操作

    3、handler代理的一些常用方法:

      get    读取

      set     修改

      has     判断对象是否有该属性

      construct     构造函数

      apply           当目标对象是一个函数的时候

      deletePrototy      用于拦截delete操作

 

十四、get/set方法

let target = {
     name: "chj",
     age: 20,
     sex: "男"
}    
let p  = new Proxy(target, {
       get(obj, attr) {
            console.log("属性被访问了");
       },
       set(obj, attr, value) {
            console.log("属性被设置了");
       }
})
p.name;
p.name = "小王";

  get函数:当访问target对象身上的一些属性的时候就会触发get函数,get函数接收两个参数

    参数一:代理的对象,也就是target。

    参数二:访问的属性。

  set函数:当设置target对象身上的一些属性的时候就会触发set函数,set参数接收三个参数

    参数一:代理的对象

    参数二:设置对象的属性

    参数三:设置对象的属性的值

  使用场景:

    1、虚拟场景

let target = {
     firstName: "chj",
     lastName: "ls"
}

let p = new Proxy(target, {
        get(obj, attr) {
               if(attr == "fullName") {
                      retrun [obj.firstName, obj.lastName].join(" ");
               }
               return obj[attr]; 
        },
        set(obj, attr, value) {
               if(attr == "fullName") {
                       let fullNameInfo = value.split(" ");
                       obj.firstName = fullNameInfo[0];
                       obj.lastName = fullNameInfo[1];
               }else {
                       obj[attr] = value;
               }
        }
})

console.log(fullName);   //chj
p.fullName = "小 甜甜";
console.log(p.firstName);     //
console.log(p.lastName);     //甜甜

  2、私有属性

//把_开头的变量都认为私有变量
let target = {
     name: "张三",
     age: 20,
     _sex: "女"
}    

let p = new Proxy(target, {
       get(obj, attr) {
              if(attr.startWith("_")) {
                    console.log("私有属性不被允许访问");
                    return false; 
              }
              return obj[attr];
       },
       set(obj, attr, value) {
              if(attr.startWith("_")) {
                    console.log("私有属性不允许设置");
                    retrun false;
              }
              obj[attr] = value;
       },
       has(obj, attr) {
              if(atrr.startWith("_")) {
                    return false;
              }
              retrun (attr in obj);
       }
})

 

十五、函数拦截

  apply:当目标对象是一个函数,且他被调用时,就是被apply方法拦截

    参数:apply(target, context, arguments) {}

      target:目标对象

      context:目标对象的上下文(this)

      arguments:目标对象的参数数组

  construct:用于拦截new命令,意思就是你在new目标对象的时候,会走construct() {}

    参数:construct(target, arguments) {}

      target:目标对象

      arguments:构造函数的参数对象

function fn(a, b) {
       lat handler = {
             apply: function(target, context, args) {
                    console.log(target, context, args)
                    return args[0];
             },

             construct: function(target, args) {
                    return {value: args[1]};
             }
       }
};

let p = new Proxy(fn, handler);

console.log(p(1, 2))           //1
console.log(new p(1, 2))    //{value: 2}

 

posted @ 2020-11-16 17:10  代码熊。  阅读(132)  评论(0)    收藏  举报