美文网首页工作生活
ES6学习笔记(四)

ES6学习笔记(四)

作者: 彼得朱 | 来源:发表于2019-07-04 18:55 被阅读0次
7.png

十五、Map和WeakMap

1、Map

用途:类似json,但是 json 的键(key)只能是字符串

​ map 的 key 可以是任意类型

使用:定义 let map = new Map();

       设置    map.set(key,value);    // 设置一个值

​ 获取 map.get(key); //获取一个值

​ 删除 map.delete(key); //删除一项

​ 判断 map.has(key); //判断

​ 清空 map.clear(); //清空

​ 循环 for(let [key,value] of map){}

​ for(let key of map.keys()){}

​ for(let value of map.values()){}

​ for(let [k,v] of map.entries()){}

​ map.forEach((val,key)=>{

​ })

// 定义
let map = new Map();
let json = {
    a: 1,
    b: 2
};

// 设置
map.set('a', 'aaa');
map.set(json, 'aaa');
map.set('aaa', json);
console.log(map); //输出 Map(3) {"a" => "aaa", {…} => "aaa", "aaa" => {…}}

// 获取
console.log(map.get('a')); //输出  aaa

// 删除
map.delete('a');
console.log(map); //输出Map(2) {{…} => "aaa", "aaa" => {…}}

//判断
console.log(map.has('a')); //输出 false

//清空
map.clear();
console.log(map); // 输出 Map(0) {}

// for循环
//重新设置

map.set('a', 'aaa');
map.set(json, 'aaa');
map.set('aaa', json);
for (let [key, value] of map) {
    console.log(key, value); //循环输出每一个键值对
}
map.forEach((value,key)=>{
    console.log(value,key);
});

注意:map和set方法很多一样,除了map 多了一个get(key)方法。

2、WeakMap

注意:key只能是对象,但是用处不大

// 定义
let map = new WeakMap();
let json = {
    a: 1,
    b: 2
};
map.set(json,'1');
console.log(map);  //输出 WeakMap {{…} => "1"}

let errmap = new WeakMap();
errmap.set('1','1');
console.log(errmap); // 输出 Uncaught TypeError

总结:Set 里面是数组,不重复,没有key,没有get方法

​ Map 对json功能增强,key可以是任意类型值

十六、数字变化和Math新增东西

1、数字(数值)变化

(1)进制

二进制(binary)

let a = 0b01010;

八进制 (Octal)

let b = 0c666;

十六进制

ccc

(2)Number方法

Number.isNaN() 等同于isNaN(),只是挂载到了Number身上

Number.isFinite() 判断是不是数字

Number.isInteger 判断是不是整数

.....

安全整数:-(253-1)~(253-1) 包含边界

Number.isSafeInteger() 判断是不是安全整数

Number.MAX_SAFE_INTEGER 最大安全整数

Number.MIN_SAFE_INTEGER 最小安全整数

2、Math

Math.abs()

Math.sqrt()

Math.sin()

Math.trunc() 截取,只保留整数部分

console.log(Math.trunc(4.5));   //输出  4
console.log(Math.trunc(-4.3));  //输出  -4

Math.sign() 判断一个数到底是正数、负数、0

console.log(Math.sign(-5));   //输出  -1
console.log(Math.sign(5));    //输出  1
console.log(Math.sign(0));    //输出  0
console.log(Math.sign(-0));   //输出  -0
console.log(Math.sign('abc'));//输出  NaN

Math.cbrt() 计算立方根

console.log(Math.cbrt(27));  //输出 3

十七、ES2018(ES9)新增东西

1、命名捕获

语法:(?<名字>)

一个例子:(日期拆分)

//以前的
let str = '2018-03-20';

let reg = /(\d{4})-(\d{2})-(\d{2})/;

let dataArr = str.match(reg);
console.log(dataArr);
let year = dataArr[1];
let month = dataArr[2];
let day = dataArr[3];
console.log(year,month,day); //输出  2018 03 20

//ES9
let str = '2018-03-20';

let reg = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;

let {year,month,day} = str.match(reg).groups;
console.log(year, month, day);  //输出  2018 03 20

反向引用: \1 \2 12

反向引用命名捕获: 语法:\k<名字>

let reg = /^(?<Strive>welcome)-\k<Strive>$/;

let str = 'a-a';
let str2 = 'Strive-Strive';
let str3 = 'welcome-welcome';
console.log(reg.test(str));  //  false
console.log(reg.test(str2)); //  false
console.log(reg.test(str3)); //  true

替换:replace

let str = '2018-03-20';

let reg = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;

str = str.replace(reg,'$<day>/$<month>/$<year>');
console.log(str);  //输出 20/03/2018
let str = '2018-03-20';

let reg = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;

str = str.replace(reg,(...args)=>{
    console.log(args);
    let {year,month,day} = args[args.length-1];
    return `${day}/${month}/${year}'`;
});
console.log(str);  //输出 20/03/2018

注意:return的时候用的是{},直接替换用的是<>

2、dotAll模式

之前:'.'在正则里面表示匹配任意东西,但是不包括\n

let reg = /\w+/gims;

3、标签函数

function fn(){

}

fn() //这样调用就是普通函数

fnaaa //注意用的是反斜杠

function fn(args){
    return args[0].toUpperCase();
}
console.log(fn`welcome`);  //输出  WELCOME

十八、Proxy的使用

作用:1、扩展(增强)对象、方法一些功能

​ 2、比如Vue中的拦截

​ 3、预警、上报、扩展、统计、增强对象等等

它是设计模式的一种,代理模式

语法:

​ new Proxy(target,handler);

​ let obj = new Proxy(被代理的对象,对代理的对象做什么操作)

​ handle{

​ set(){} //设置的时候干的事情

​ get(){} //获取干的事情

​ deleteProperty(){} //删除

​ has(){} //问你有没有这个东西 'xxx' in obj

​ apply() //调用函数处理,拦截方法

​ .......

​ }

例1:(增加一个代理对象,访问不是原对象属性时会抛出错误,这些是访问之前的操作)

let obj = {
    name:'Strive'
}

let newObj = new Proxy(obj,{
    get(target,property){
        // 访问之前可以做的操作
        console.log(`您访问了${property}属性`);  //您访问了name属性
        if(property in target){
            return target[property];
        }else{
            throw new ReferenceError(`${property}属性不在此对象上`);
        }
    }
})

console.log(newObj.name);  //Strive
console.log(newObj.age);   //没加判断之前访问默认是 undefined,加了之后会
//显示Uncaught ReferenceError: age属性不在此对象上

例2:DOM.div() DOM.a(); DOM.ul()

const DOM = new Proxy({},{
    get(target,property){
        return function(attr={},...children){
            const el = document.createElement(property);

            // 添加属性
            for(let key of Object.keys(attr)){
                el.setAttribute(key,attr[key]);
            }
            // 添加子元素
            for(let child of children){
                if(typeof child == 'string'){
                    child = document.createTextNode(child);
                }
                el.appendChild(child);
            }

            return el;
        }
    }
});

let oDiv = DOM.div(
    {id:'div1',class:'aaa'},'我是div','哈哈哈',
    DOM.a({href:'http://www.baidu.com'},'访问官网'),
    DOM.ul({},
           DOM.li({},'1111'),
           DOM.li({},'2222')
          )
)

window.onload = function(){
    document.body.appendChild(oDiv);
}

运行结果:

2.png

例3:set(),设置拦截,设置一个年龄,保证是整数,且范围不超过200

let obj = new Proxy({},{
    set(target,prop,value){
        if(prop == 'age'){
            if(!Number.isInteger(value)){
                throw new TypeError('年龄必须为整数');
            }
            if(value>200){
                throw new RangeError('年龄超标了,必须小于200岁');
            }
        }
        target[prop] = value;
    }
});

obj.a = 123;
obj.name = 'strive';
obj.age = 220;
console.log(obj);    //输出  Uncaught RangeError: 年龄超标了,必须小于200岁
        

例3:deleteProperty()、has()

let json = {
    a:1,
    b:2
}   

let newJson = new Proxy(json,{
    deleteProperty(target,property){
        console.log(`您要删除${property}属性`);   //输出 您要删除a属性
        delete target[property];
    },
    has(target,property){
        console.log('判断是否存在调用has方法');   // 输出 判断是否存在调用has方法
        return property in target;
    }
});

console.log('a' in newJson);// 这里调用 has 方法,输出true
delete newJson.a;      // 这里调用 delete 方法
console.log(newJson);  // 输出 Proxy {b: 2}

例4:apply() :拦截

function fn(){
    return '我是函数';
}
let newfn = new Proxy(fn,{
    apply(){
        return '函数吗?';
    }
});
console.log(newfn());  //输出 函数吗?

注意:apply()上面的只是拦截到了,并没有执行完函数,需要和reflect配合使用

十九、Reflect的使用

反射。(相对于执行函数)

Reflect.apply(调用的函数,this指向,参数数组);

与fn.apply() 类似

Reflect :思想 通过Reflect对象身上直接拿到语言内部东西

//例1
function sum(a,b){
    return a+b;
}

let newSum = new Proxy(sum,{
    apply(target,context,args){
        return Reflect.apply(...arguments);  //反射调用
    }
});

console.log(newSum(2,3));  //前面加了reflect,这里可以得到 5
//例2
function show(...args){
    console.log(this);   
    console.log(args);   
}

show(1,2,3,4);        // 只有参数,this指向:window  args:[1, 2, 3, 4]
show.call('abc',1,2,3,4);// this指向:String {"abc"} args:[1, 2, 3, 4]
show.apply('abcd',[2,3,3,2]);//this指向:String {"abcd"}  args:[2, 3, 3, 2]
Reflect.apply(show,'aaaa',[1,2,3,4]);//this指向:String {"aaaa"}  args:[1, 2, 3, 4]
//例3
console.log(Reflect.has(Object,'assign')); //输出true
//例3
let json = {a:1,b:2};
// delete json.a;
Reflect.deleteProperty(json,'a');  //等同于上面这句
console.log(json); //输出  {b: 2}

相关文章

网友评论

    本文标题:ES6学习笔记(四)

    本文链接:https://www.haomeiwen.com/subject/hcqdhctx.html