[译] 一些ES6的小技巧

[译] 一些ES6的小技巧

大家好,又见面了,我是全栈君。

原文: Check out these useful ECMAScript 2015 (ES6) tips and tricks

有任何错误请在评论指出,感激不尽。

EcmaScript 2015 (ES6) 已经出现了很多年了,我们可以使用它的一些新特性。

1.设置必须的函数参数

ES6 提供了 默认的参数值,可以让你在函数的参数中指定默认值当参数没有传递其值的时候。

const required = () => {
   
   throw new Error('Missing parameter')};
//The below function will trow an error if either "a" or "b" is missing.
const add = (a = required(), b = required()) => a + b;
add(1, 2) //3
add(1) // Error: Missing parameter.
复制代码

在这个例子中,我们对函数 add 的参数 ab 设置了一个默认值,这个默认值为一个函数。当函数 add 被执行时,且参数 ab 有一个没有传递值的时候,这个 required 函数就会执行,我们就会得到一个报错 Error: Missing parameter.

2.非常强力的”reduce”

Array 的方法 reduce 是一个有非常多用处的函数。 它一个非常具有代表性的作用是将一个数组转换成一个值。但是你可以用它来做更多的事。

? Tip: 这些小技巧的的初始值都是一个数组或者一个对象而不是一个像字符串之类的简单的值

2.1 使用reduce做到同时有map和filter的作用

假设有这样的一个场景,你有一个list,里面有一些item, 你需要更新这些item, 更新完以后你需要使用filter来过滤掉你不需要的item。但是这样的话你需要遍历这个数组两次!

const numbers = [10, 20, 30, 40];
const doubledOver50 = numbers.reduce((finalList, num) => {
  
  num = num * 2; //double each number (i.e. map)
  
  //filter number > 50
  if (num > 50) {
    finalList.push(num);
  }
  return finalList;
}, []);
doubledOver50; // [60, 80]
复制代码

在这个例子里面,我们想要让数组里面的值翻倍,然后我们只想要里面大于 50 的元素。注意一下我们是如何使用 reduce 方法做到同时有让元素的值翻倍,然后过滤的。

2.2 使用”reduce”代替”map”和”filter”

在原文中没有体现这部分代码,只说了注意2.1的代码。在这里我添加一下这部分代码:

2.2.1 使用”reduce”代替”map”
function map(arr, exec) {
    var res = arr.reduce((res, item, index) => {
        var newItem = exec(item, index)
        res.push(newItem)
        return res
    }, [])
    return res
}

[1, 2, 3].map((item) => item * 2) // [2, 4, 6]

map([1, 2, 3], item => item * 2) // [2, 4, 6]
复制代码
2.2.2 使用”reduce”代替”filter”
function filter(arr, exec) {
    var res = arr.reduce((res, item, index) => {
        if (exec(item, index)) {
            res.push(item)
        }
        return res
    }, [])
    return res
}

[1, 2, 3].filter((item, index) => index < 2) // [1, 2]
filter([1, 2, 3], (item, index) => index < 2) // [1, 2]
复制代码

2.3 使用”redece”来判断括号是否匹配

这也是个例子来说明 reduce 这个函数功能的强大。给你一串字符串,你想要知道这串字符串的括号是否是匹配的。

常规的做法是使用栈来匹配,但是这里我们使用 reduce 就可以做到,我们只需要一个变量 counter ,这个变量的初始值是 0 , 当遇到 ( 的时候,counter ++ 当遇到 ) 的时候, counter -- 。 如果括号是匹配的,那么这个 counter 最终的值是0

//Returns 0 if balanced.
const isParensBalanced = (str) => {
  return str.split('').reduce((counter, char) => {
    if(counter < 0) { //matched ")" before "("
      return counter;
    } else if(char === '(') {
      return ++counter;
    } else if(char === ')') {
      return --counter;
    }  else { //matched some other char
      return counter;
    }
    
  }, 0); //<-- starting value of the counter
}
isParensBalanced('(())') // 0 <-- balanced
isParensBalanced('(asdfds)') //0 <-- balanced
isParensBalanced('(()') // 1 <-- not balanced
isParensBalanced(')(') // -1 <-- not balanced
复制代码

2.4 计算数组中元素出现的次数(将数组转为对象)

如果你想计算数组中元素出现的次数或者想把数组转为对象,那么你可以使用 reduce 来做到。

var cars = ['BMW','Benz', 'Benz', 'Tesla', 'BMW', 'Toyota'];
var carsObj = cars.reduce(function (obj, name) { 
   obj[name] = obj[name] ? ++obj[name] : 1;
  return obj;
}, {});
carsObj; // => { BMW: 2, Benz: 2, Tesla: 1, Toyota: 1 }
复制代码

作者建议前往MDN学习,查看更多例子MDN

// 我也去看了一眼MDN,发现reduce真是个黑科技,promise串行这个应用非常秒啊。

3.对象解构

3.1 移除不想要的属性

有时候你想要移除对象中的一些不需要的属性,这个对象可能是包含了某些敏感的信息或者只是因为这个对象太大了。我们可以使用解构来代替去遍历这些属性。

let {_internal, tooBig, ...cleanObject} = {
   
   el1: '1', _internal:"secret", tooBig:{}, el2: '2', el3: '3'};
console.log(cleanObject); // {el1: '1', el2: '2', el3: '3'}
复制代码

在这个例子中,我们想要移除 _internaltooBig 这两个属性,我们可以将他们分配给变量 _internaltooBig 中,剩下的属性存放在 cleanObject 中,这就是我们想要的。

3.2 在函数参数中使用嵌套对象解构

var car = {
  model: 'bmw 2018',
  engine: {
    v6: true,
    turbo: true,
    vin: 12345
  }
}
const modelAndVIN = ({model, engine: {vin}}) => {
  console.log(`model: ${model} vin: ${vin}`);
}
modelAndVIN(car); // => model: bmw 2018 vin: 12345
复制代码

在这个例子中 engine 是一个嵌套在 car 里面的对象,如果我们只需要 engine 里面的属性 vin 我们可以这样做。

3.3 合并对象

ES6 新增了一个扩展运算符,... 使用三个点来表示,它经常用来解构数组的值, 但是它也可以用在对象中。

在这个例子中,我们在一个新的对象中使用扩展运算符,后面一个对象的属性值会把前面一个对象的属性值覆盖。

第二个对象中的属性 bc 的值把第一个对象中属性 bc 的值覆盖掉了

let object1 = { a:1, b:2,c:3 }
let object2 = { b:30, c:40, d:50}
let merged = {…object1, …object2} //spread and re-add into merged
console.log(merged) // {a:1, b:30, c:40, d:50}
复制代码

4.Sets

4.1 使用set来对数组去重

在ES6可以很方便的使用Set来对数组去重,因为Set表示的是一个集合,一个元素会在集合里面出现过一次。

let arr = [1, 1, 2, 2, 3, 3];
let deduped = [...new Set(arr)] // [1, 2, 3]
复制代码
4.2 使用Array的方法

可以通过(…)扩展运算符将 Set 转换成 Array 这样我们就可以在 Set 使用所有 Array 的方法了。

这个例子展示了如何在 Set 中使用 filter 方法

let mySet = new Set([1,2, 3, 4, 5]);
var filtered = [...mySet].filter((x) => x > 3) // [4, 5]
复制代码

5.数组的解构

5.1 交换2个值

let param1 = 1;
let param2 = 2;
//swap and assign param1 & param2 each others values
[param1, param2] = [param2, param1];
console.log(param1) // 2
console.log(param2) // 1
复制代码

5.2 函数返回多个值

async function getFullPost(){
  return await Promise.all([
    fetch('/post'),
    fetch('/comments')
  ]);
}
// const [post, comments] = getFullPost();
const [post, comments] = await getFullPost();
// 注释掉的那一行是作者写的,但是我跑不通,我觉得getFullPost是个Promise,所以需要加await。
复制代码

我们使用 async\await 来获取2个接口的数据 /post/comments , 函数返回的是一个数组,所以可以使用解构来获得这两个接口的返回值。

作者原文章的内容就到这里,但是我想补充一下map。

6. Map

在对象中的 key 只能是 string 没办法接受一个 Object 当作 key 会被自动转换成字符串,例子如下:

const data = {};
const element = document.getElementById('myDiv');

data[element] = 'metadata';
data['[object HTMLDivElement]'] // "metadata"
复制代码

所以对于键值对的数据解构,mapObject 更加合适。

6.1 在map中使用对象当作key

const M = new Map()
let o = {
   
   p: 'Hello World'}
M.set(o, 'hello world')
M.get(o) // hello world
let O = {
   
   p: 'Hello World'}
M.get(O) // undefined
复制代码

注意: O != o 所以这个 M.get(O)undefined

6.2 WeakMap的作用

在普通的map中,如果一个 object 被当作 key 引用了,当除了map以外,其他的变量都丢掉对这个 object 的引用,那map还是会阻止垃圾回收机制去回收这个 object 这就会导致内存泄漏。所以就有了WeakMap。

字面意思,WeakMap里面的key是弱引用,并且 WeakMap中只能以 Object 当作 key 因为其他的你都可以用 Map搞啊~~那么 WeakMap的几个小技巧。

6.2.1 使用DOM节点作为键名
let myElement = document.getElementById('logo');
let myWeakmap = new WeakMap();

myWeakmap.set(myElement, {
   
   timesClicked: 0});

myElement.addEventListener('click', function() {
  let logoData = myWeakmap.get(myElement);
  logoData.timesClicked++;
}, false);
复制代码

以上例子来自 Ruanyifeng

我们用WeakMap来存DOM节点的某些状态,当这个DOM节点被删除时,myElement失去了引用,全世界都失去了引用,WeakMap里面所存的状态就会消失,所以不会存在内存泄漏的问题。

6.2.2 使用WeakMap来部署私有属性

我们都知道,在JS中实现实例的私有属性是比较困难的,有个办法是使用闭包,但是闭包有个问题,实例被强引用,不能被垃圾回收机制处理。如下代码:

var Person = (function() {
    var privateData = {},
        privateId = 0;
    function Person(name) {
        Object.defineProperty(this, "_id", { value: privateId++ });
        privateData[this._id] = {
            name: name
        };
    }
    Person.prototype.getName = function() {
        return privateData[this._id].name;
    };
    return Person;
}());
复制代码

privateData对每个实例都是强引用,所以垃圾回收机制是处理不了的。

我们可以用weakMap很好的解决这个问题。

var privateData = new WeakMap();
var Person = (function() {
    function Person(name) {
        privateData.set(this, { name: name });
    }
    Person.prototype.getName = function() {
        return privateData.get(this).name;
    };
    return Person;
}());
复制代码

以上代码weakMap不会对实例造成强引用,也就是说,垃圾回收机制是可能把这个实例回收掉的,如果没有其他人对这个实例保持着引用,是会被回收的,也就不会导致内存泄露了。

以上例子来自JavaScript实现私有属性

转载于:https://juejin.im/post/5ac23113f265da23906c2fbc

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/107603.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • ETCD锁

    ETCD锁etcd 中的锁是 tryLock 模式 每次 lock 都是尝试 lock 也就是尝试锁定某个 key 如果该 key 当前状态下是被锁定的话 就无法锁定 引入 etcd 租约 该租约的效果是给该锁添加失效时长 租约到期 该锁失效 自动释放 代码如下 importjava util concurrent ExecutionExc importjava util concurrent Time

    2025年11月21日
    3
  • java 常量表达式,需要常量表达式? (Java switch语句)[通俗易懂]

    java 常量表达式,需要常量表达式? (Java switch语句)[通俗易懂]Ihavenoideawhatiscausingthiserror.MyteacherandIwentoveritandcouldn’tfindwhatwaswrong.importjava.util.Scanner;publicclassMailAssignment{publicstaticvoidmain(String[]args){S…

    2022年9月29日
    4
  • 基于51单片机的交通灯控制系统设计开题报告_交通灯控制系统设计的毕业论文

    基于51单片机的交通灯控制系统设计开题报告_交通灯控制系统设计的毕业论文摘要交通灯是生活中的重要系统。本设计为基于51单片机交通灯系统的设计,采用模块化、层次化设计。运用单片机AT89C51进行数据的分析和处理,为显示提供信号,显示部分采用8位数码管显示倒计时值。系统电路简单、集成度高、工作稳定、调试方便、检测精度高,具有一定的实用价值。【关键词】AT89C518位数码管发光二级管按键

    2022年9月25日
    3
  • pycharm怎么更新包_python 开发web项目

    pycharm怎么更新包_python 开发web项目运行环境使用的是python2.5,想在项目中换成python3.6,安装完Python3.6后。打开Pycharm:File->Settings->找到project:*******->ProjectInterpreter,然后直接在下拉框里选择你已经安装的好的版本(只要在系统里安装好python版本,配置好环境变量,Pycharm会自动加载)。确认即可统一…

    2022年8月29日
    4
  • 哪些网站需要大量资深工程师开发

    先出一道题考考你:下列哪个网站目前不需要大量顶尖高手开发A.淘宝网B.FacebookC.何问起D.百度答案:http://hovertree.com/tiku/bjaf/861yt2f7.ht

    2021年12月25日
    42
  • python执行测试用例_测试用例是由什么组成

    python执行测试用例_测试用例是由什么组成前言通常我们认为每个测试用例都是相互独立的,因此需要保证测试结果不依赖于测试顺序,以不同的顺序运行测试用例,可以得到相同的结果。pytest默认运行用例的顺序是按模块和用例命名的ASCII编码

    2022年7月29日
    8

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号