美文网首页
es6的一些骚操作

es6的一些骚操作

作者: 喜欢未来你的我 | 来源:发表于2019-01-21 14:12 被阅读0次
    • 简洁高效的解构语法
    • 遍历写法(数组与对象)
    • 定义与获取对象属性描述
    • 总结

    前言

    写博客,在犹豫一会,价值度不高,非知识开拓性,无非几十分钟,几个小时写完的作文一样,点击发布交卷,之后期待别人的评分点赞?技术重复分享,搞得像是无耻的事一样,不,我也这么这么做,反正也闲的蛋疼,嘻嘻嘻。其实想多了,纯粹的分享,才不会想或者在乎呢,分享个人经验与看法,或是分享已有的知识见解,都是个体情感产生的,万一有一个小弟看着,就与你产生共契合,帮助到别人,当然是很好的。写博客,其实想表达的,自己对知识点的见解而已,虽然粗陋,也是给自己看的,谁会嫌弃自己的佳作的呢。

    简洁高效的语法

    es6新增了很多简洁风格,使其代码清爽便捷了许多。

    模版字符串

    模版字符串很常用,分两类应用场景。
    一,书写整齐的HTML片段,避免了‘一行到底’与字符串拼接;
    二,应用于字符串与变量随性组合拼接。

    比较常用,附上小例子

    const name = '章';
    $('.container').prepend(
        '<div>' + 
            '<span> 额hi额黑' + name + '</span>' +
        '</div>'
    )
    // 模版字符串
    $('.container').prepend(`
        <div>
            <span>额hi额黑 ${name}</span>
        </div>
    `)
    
    函数传参默认值

    定义函数的时候,有时或者需求上需将形参设置为指定的备选值或叫默认值。

    小例子,结合具名函数与匿名函数,以及用上模版字符串

    function person (name,species) {
        species = species || 'person';
        console.log(species + ',It name is:' + name);
    }
    const person = function (name,species = 'person') {
        console.log(`${species},It name is:${name}`);
    }
    

    注意:函数形参不能有同名参数,会报错。
    也是,当然直接这么用,也体现不了多少简洁或是方便。函数默认赋值,一般与解构赋值结合

    // 函数参数为对象
    function foo({x,y=5}) {
        console.log(x,y);
    }
    foo(); // 报错,实参不为对象肯定报错呗
    foo({}); // undefind 5; 函数默认值为5
    
    // 简单网络请求的封装函数,函数格式(字符串,对象)
    function fetch(url,{ body = '', method = 'get', headers = {} }) {
        console.log(method);
    }
    fetch('https://www.hp.com',{});  // 'get',函数默认值为get
    fetch('https://www.hp.com');     // 传格式不对,报错
    
    // 上述例子,格式定要传对象,否则缺少参数就会报错,可以改良,给对象也一个默认值
    function fetch(url,{ body = '', method = 'get', headers = {} } = {}) {
        console.log(method);
    }
    fetch('https://www.hp.com');  // ‘get’
    
    // 若指定某个参数不能省略,又想自定义抛出错误(默认值应用)
    function customError () {
        throw new Error('必须传一个对象,否则我就报错这条错误信息。');
    }
     function foo({x,y=5} = customError()) {
        console.log(x,y);
    }
    foo(); // 报错,必须传一个对象,否则我就报错这条错误信息  
    
    扩展运算符

    扩展运算符,一般与es6新增的rest结合使用。rest参数就类似于arguments对象,收集实参信息,(形式...变量名),就想当于将实参里面每项罗列出来。

    来个小例子,运行下

    (function (){
        console.log(arguments); //{ '0': 1, '1': 2, '2': 3, '3': 4, '4': 'a', '5': 2, '6': 3 }
        Object.values(arguments).forEach(v => {
            console.log(v);
        });
    })(1,2,3,4,'a',2,3);
    
    (function (...values){
        console.log(values); // [ 1, 2, 3, 4, 'a', 2, 3 ]
        values.forEach(v => {
            console.log(v);
        })
    })(1,2,3,4,'a',2,3);
    
    (function (...values){
        console.log(values); // [ { a: 1, b: true, c: 'hello' }, { b: 1 } ]
        values.forEach(v => {
            console.log(v);
        })
    })({a:1,b: true, c: 'hello'},{b: 1})
    

    上述代码,写了个匿名函数传参自调用,可以看出arguments参数是一个实参对象。键值对形式,键为位置下标。而使用rest参数,可以获得实参选项对应数组,便于遍历。

    遍历写法(数组与对象)

    遍历,在平平常常的开发中,使用频率蛮高的。我们总会喜欢一种或几种写法,这无可厚非。但是常用不一定合适,或是不一定一次性代码解决需求问题。所以下面总结,遍历所有场景与方法,便于冲锋般的急促中,想起身上还有一个不常用但迅速杀一窝敌的手雷。崩————GG,阵亡

    1. for循环

    for 循环,想必大学听着基本语法结构。但是好像在实际开发中,没怎么用过。反正我是没用过,但是很有用滴~

    写个例子

    const arr = [1,2,1,'c',true];
    for(let i =0; i < arr.length;i++) {
        console.log(arr[i]); // 循环获取数组的值与下标
    }
    
    2. forEach循环

    forEach循环,数组遍历常用的一种。注意,返回值为undefined;唯一能够跳出循环的,通过try{}catch(err) { throw ' Error Info'}类似抛出异常结构,终止循环(注意的是,将遍历循环代码放在try...catch结构内)。不会响应break、continue、return语句。其中break,结束循环的进程;continue,结束本轮循环;return,跳出函数并返回值。

    写个例子

    const traverseArr = ['1','2', '3', 'asdf',true, 2];
    let resultStr = traverseArr.forEach((item,index,array) => {
        console.log(item); // 数组当前选中值
        console.log(index); // 数组当前选中的下标
        if(item === 'asdf') {
            console.log('数组里面的true,2不会打印!');   // 没有效果,不响应break语句
            break;
        }
        console.log(array); // 数组本身
    })
    console.log(resultStr); // undefined
    -----------
    try {
        let resultStr = traverseArr.forEach((item,index,array) => {
            console.log(item);
            if(item === 'asdf') {
                throw 'asdf值以后的值,不会打印了。结束循环了'
            }
        })
    } catch (err) {
        console.log(err);
    }
    
    3.for... of遍历

    for...of遍历数组 , 可以正确响应break、continue和return语句

    写个例子

    const traverseArr = ['1','2', '3', 'asdf',true, 2];
    for(item of traverseArr) {
        console.log(item);
        if(item === 'asdf') {
            console.log('确实不会打印asdf里面的值!');
            break;
        }
    }
    
    4.map遍历

    map遍历是很常用的一种,支持返回值为处理后的数组,数组中的元素为原始数组元素调用函数处理后的值。 可以发现,返回值为深拷贝

    写个例子

    const traverseArr = ['1','2', '3', 'asdf',true, 2];
    let resultArr = traverseArr.map((item,index,arr) => {
        if(item === '3') {
            return '2';
        }
        return item;
    });
    console.log(traverseArr);  // [ '1', '2', '3', 'asdf', true, 2 ]
    console.log(resultArr);    // [ '1', '2', '2', 'asdf', true, 2 ]
    
    5.filter遍历

    filter遍历, 不会对空数组进行检测,不会改变原始数组,返回新数组。一般用于过滤数组

    写个例子

    const traverseArr = [
        {name: 'yy',age: 24, denger: 'man',isFirst: true},
        {name: 'lz', age: 23,denger: 'man',isFirst: false},
        {name: 'laz', age: 23,denger: 'woman',isFirst: true},
    ]
    let resultArr = traverseArr.filter((v,i,arr) => v.denger === 'woman');
    console.log(traverseArr);   // [ { name: 'yy', age: 24, denger: 'man', isFirst: true },{ name: 'lz', age: 23, denger: 'man', isFirst: false },
    { name: 'laz', age: 23, denger: 'woman', isFirst: true } ]
    console.log(resultArr);  // [ { name: 'laz', age: 23, denger: 'woman', isFirst: true } ]
    
    6.every遍历

    every遍历,用于检测数组所有元素是否都符合指定条件,如果所有元素都满足条件,则返回 true。其实蛮有作用的,一开始我们可能设置标志位,然后遍历每一项,来更改标志位状态。与some遍历相比,相当于逻辑与的操作

    写个例子

    const traverseArr = [
        {name: 'yy',age: 24, denger: 'woman',isFirst: true},
        {name: 'lz', age: 23,denger: 'woman',isFirst: false},
        {name: 'laz', age: 23,denger: 'woman',isFirst: true},
    ];
    let isAllWomen = traverseArr.every((v,i,arr) => {
        if(v.denger === 'woman') {
            return true;
        }
        return false;
    })
    console.log(isAllWomen); // true
    
    7.some遍历

    some遍历, 用于检测数组中的元素是否用满足指定条件的,如果有一个元素满足条件,剩余的元素不会再执行检测。返回值,若如果数组中有元素满足条件返回true,且终止循环

    写个例子

    const traverseArr = [
        {name: 'yy',age: 24, denger: 'woman',isFirst: true},
        {name: 'lz', age: 23,denger: 'man',isFirst: false},
        {name: 'laz', age: 23,denger: 'man',isFirst: true},
    ];
    let isHasWomen = traverseArr.some((v,i,arr) => {
        console.log(v);
        if(v.denger === 'woman') {
            return true;
        }
        return false;
    })
    console.log(isHasWomen);  
    
    8.reduce遍历

    reduce遍历,接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。返回值,为返回计算结果

    写个例子

    // 获取数组值得总和
    const traverseArr = [
        {name: 'yy',age: 24, denger: 'woman',isFirst: true},
        {name: 'lz', age: 23,denger: 'man',isFirst: false},
        {name: 'laz', age: 21,denger: 'man',isFirst: true},
    ];
    let totalAge = traverseArr.reduce((total,v,i,arr) => {
        return total + v.age;
    },0);
    console.log(totalAge); // 68
    --------
    // 获取数组最大值
    const traverseArr = [
        {name: 'yy',age: 24, denger: 'woman',isFirst: true},
        {name: 'lz', age: 23,denger: 'man',isFirst: false},
        {name: 'laz', age: 21,denger: 'man',isFirst: true},
    ];
    let maxVal = traverseArr.reduce((prev,cur) => {
        return Math.max(prev,cur.age)
    },0);
    console.log(maxVal); // 24
    
    9.reduceRight遍历

    reduceRight遍历,方法的功能和reduce()功能是一样的,不同的是reduceRight()从数组的末尾向前将数组中的数组项做累加。

    10.for...in遍历

    in 关键字遍历对象属性和原型上的属性(可遍历属性)。for...in遍历,一般用于遍历对象属性,但也可以遍历数组

    写个例子

    const traverseArr = [
        {name: 'yy',age: 24, denger: 'woman',isFirst: true},
        {name: 'lz', age: 23,denger: 'man',isFirst: false},
        {name: 'laz', age: 21,denger: 'man',isFirst: true},
    ];
    const objH = {
        name: 'name',
        age: 23,
        gender: 'man'
    }
    for(is1 in traverseArr) {
        console.log(traverseArr[is1]);
    }
    for(i in objH) {
        console.log(traverseArr[is1]);
    }
    
    11.es6新增 keys,values,entries

    ES6 提供三个新的方法 —— entries(),keys()和values() —— 用于遍历数组。它们都返回一个遍历器对象

    写个例子

    const arr = [2,true,'hello'];
    console.log(arr.values());  // Object [Array Iterator] {}
    console.log(arr.keys());  // Object [Array Iterator] {}
    console.log(arr.entries());  // Object [Array Iterator] {}
    
    for(let [v,i] of arr.entries()) {
        console.log(v);  // 下标
        console.log(i);  // 值
    }
    for(let v of arr.keys()) {
        console.log(v); // 值
    }
    for(let v of arr.values()) {
        console.log(v); // 值
    }
    
    12.find遍历

    find遍历,返回通过测试(函数内判断)的数组的第一个元素的值,注意,当数组中的元素在测试条件时返回 true 时, find() 返回符合条件的元素。跟some遍历类似,符合条件停止遍历,但some遍历返回的状态

    写个例子

    const arr = [2,3,true,'hello','xixi',2];
    
    let firstVal = arr.find((val,index,arr) => {
        console.log(val);
        if(val === 'hello') {
            return true;
        }
    }); // 遍历打印: 2 3 true hello
    
    console.log(firstVal); // hello
    
    13.findIndex 遍历

    findIndex遍历, 返回传入一个测试条件(函数)符合条件的数组第一个元素位置(下标)。

    14.对象遍历 Object.keys()、Object.values()、Object.entries()

    我们知道<code>in</code>关键字,遍历对象属性但也遍历该对象原型链上的可遍历属性。而现在介绍的属性,遍历的是本身对象可遍历的属性。

    写个例子

    const obj = {
    name: 'yangyi',
    age: 23,
    gender: 'woman',
    say() {
        console.log('hello beatuify world!');
    }
    }; 
    const parent = {
        sex: true,
        sayHei: function (name) {
            console.log(`hello ${name}!`);
        }
    };
    
    Object.setPrototypeOf(obj,parent); // 建立原型链
    
    // Object.keys()
    console.log(Object.keys(obj));  // [ 'name', 'age', 'gender', 'say' ]
    Object.keys(obj).forEach(v => {
        console.log(v); // 打印: name,age,gender,say
    });
    // for ... in 可遍历原型上的属性
    for(key in obj) {
        console.log(key);  // 打印对象本身及原型上的key值
    }  
    ----------
    // Object.values()
    console.log(Object.values(obj));
    Object.values(obj).forEach(v => {
        console.log(v)
    })
    ----------
    // Object.entries()
    console.log(Object.entries(obj)); // [ [ 'name', 'yangyi' ],[ 'age', 23 ],[ 'gender', 'woman' ],[ 'say', [Function: say] ] ]
    for([k,v] of Object.entries(obj)) {  
        console.log(k);
        console.log(v);
    }
    

    注意的是,使用Object.entries()返回二维数组格式。我们也可以通过Object.fromEntries()将一个键值对数组转为对象。

    定义与获取对象属性描述

    本小节,主要了解的是对象本身属性描述,定义描述与获取描述。其中,介绍一下,属性描述符主要分为两类,数据描述符和存取描述符。数据描述符是一个具有值的属性,而存取描述符是由getter-setter函数对描述的属性。

    了解一下具体属性描述符:

    1. configurable,该值为 true 时,该属性描述符才能够被配置改变,否则无法重新设置。
    2. enumerable, 该值为true时,该属性才能够出现在对象的枚举属性中
    3. value, 该属性对应的值,默认为undefined。
    4. writable,该属性的writable值为true,value才能被修改。
    5. get, 属性提供 getter 的方法,如果没有 getter 则为 undefined。
    6. set, 属性提供 setter 的方法,如果没有 setter 则为 undefined.

    注意,描述符(value或writable)和(get或set)关键字不能同时存在,否则会抛出一个错误。如果一个描述符不具有value,writable,get 和 set 任意一个关键字,那么它将被认为是一个数据描述符

    大致了解了属性描述符,现在我们看看与它有关的方法:

    Object.defineProperty()和Object.defineProperties(),定义对象的属性描述符

    写个小例子,定义一个对象的属性的值不可修改,不可遍历,不可重新配置

    let descriptorObj = {};
    let descriptor = Object.create(null);
    // 默认没有 enumerable,没有 configurable,没有 writable
    descriptor.value = 'static';
    Object.defineProperty(descriptorObj,'key',descriptor);
    console.log(descriptorObj.key);
    descriptorObj.key = 'write';  
    console.log(descriptorObj.key); // 打印static,不可修改
    
    for(key in descriptorObj) {
        console.log(key,'打印'); // 不可遍历
    };
    
    Object.defineProperty(descriptorObj,'key',{  // 报错
        value: '重新修改这个值',
        enumerable: true,
        writable: true,
        configurable: true
    })
    

    注意上述,通过 Object.create(null)将proto属性指向null,然后指定对象value描述符,其它描述符不指定,则默认false。如果想同时配置对象的多个属性的属性描述符,可以使用Object.defineProperties()方法

    let descriptorObj = {
    name: 'yangyi',
    age: 24,
    denger: 'woman'
    };
    
    Object.defineProperties(descriptorObj, {
        name: {
            value: 'yangyi1',
            writable: true,
            enumerable: false,
            configurable: true
        },
        age: {
            value: 25,
            enumerable: true,
            writable: false,
            configurable: true
        },
        denger: {
            value: 'man',
            writable: false,
            enumerable: true,
            configurable: false
        }
    });
    console.log(Object.getOwnPropertyDescriptors(descriptorObj));
    
    Object.keys(descriptorObj).forEach(v => {
        console.log(v); // age denger
    });
    
    console.log(descriptorObj.age); // 25
    descriptorObj.age = 26; // age属性描述符不可重写
    console.log(descriptorObj.age); // 25
    
    Object.defineProperty(descriptorObj,'denger',{  // 报错
        writable: true,
        configurable: true
    })
    

    上述定义对象多个属性的描述符代码中,使用getOwnPropertyDescriptors获取对象属性的描述符。下面就介绍获取对象描述符的方法

    Object.getOwnPropertyDescriptors() 和Object.getOwnPropertyDescriptor(),获取对象的属性描述符
    let descriptorObj = {
    name: 'yangyi',
    age: 24,
    denger: 'woman'
    };
    
    Object.defineProperties(descriptorObj, {
        name: {
            value: 'yangyi1',
            writable: true,
            enumerable: false,
            configurable: true
        },
        age: {
            value: 25,
            enumerable: true,
            writable: false,
            configurable: true
        },
        denger: {
            value: 'man',
            writable: false,
            enumerable: true,
            configurable: false
        }
    });
    console.log(Object.getOwnPropertyDescriptors(descriptorObj));
    ---打印值--
    { name: 
        { 
            value: 'yangyi1',
            writable: true,
            enumerable: false,
            configurable: true 
        },
    age: 
        {
            value: 25,
            writable: false,
            enumerable: true,
            configurable: true 
        },
    denger: 
        {
            value: 'man',
            writable: false,
            enumerable: true,
            configurable: false 
        } 
    }
    
    console.log(Object.getOwnPropertyDescriptor(descriptorObj,'denger'));
    ---打印值----
    { 
        value: 'man',
        writable: false,
        enumerable: true,
        configurable: false 
    }
    

    总结

    怎么说呢,分享的其实是技术面的扩展,便于记忆,以及工作开发效率。其实真正的技术,还是不断深究其里,每个技术的细枝末节。不过始终相信,保持热情、耐心,一点点的去进步,相信会获得更多。

    爱代码,爱生活

    参考
    es6 阮一峰

    laozhang.jpg

    相关文章

      网友评论

          本文标题:es6的一些骚操作

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