[译] 一些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

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 常用jar包下载地址

    常用jar包下载地址http://www.java2s.com/Code/Jar/CatalogJar.htm

  • PKI体系快速了解「建议收藏」

    PKI体系快速了解「建议收藏」首先,PKI(PublicKeyInfrastructure)是一个体系。公钥基础设施是一个包括硬件、软件、人员、策略和规程的集合,用来实现基于公钥密码体制的密钥和证书的产生、管理、存储、分发和撤销等功能。PKI体系是计算机软硬件、权威机构及应用系统的结合。它为实施电子商务、电子政务、办公自动化等提供了基本的安全服务,从而使那些彼此不认识或距离很远的用户能通过信任链安全地交流。—百度百科说白了,PKI还是提供了彼此身份确认的服务,确保通信的安全。…

  • setScale,preScale 和 postScale 的区别

    setScale,preScale 和 postScale 的区别setScale,preScale和postScale的区别上面讲到,Matrix由3*3矩阵中9个值来决定。而我们对Matrix的所有设置,也是对这9个值的各种不同的改变,来达到我们想要的效果。下面是Matrix3*3的矩阵结构{MSCALE_X,MSKEW_X,MTRANS_X,MSKEW_Y,MSCALE_Y,MTRANS_Y,MPERSP_0,MPERSP_1,MPERSP_2}一、首先介绍Scale缩放的控制scale就是缩放,我们调用Matrix的setScale、preSc

    2022年10月20日
  • DialogResult的使用方法

    DialogResult的使用方法usingSystem;usingSystem.Collections.Generic;usingSystem.ComponentModel;usingSystem.Data;usingSystem.Drawing;usingSystem.Linq;usingSystem.Text;usingSystem.Windows.Forms;namespace_2014

  • SSL 中证书能否够使用IP而不是域名[通俗易懂]

    SSL 中证书能否够使用IP而不是域名

  • 适配器的作用[通俗易懂]

    适配器的作用[通俗易懂]首先我们从一般的概念上讨论一下计算机是怎样连接到局域网上的。计算机与外界局域网的连接是通过通信适配器(adapter)。适配器本来是在主机箱内插入的一块网络接口板(或者是在笔记本电脑中插入一块PCMCIA卡)。这种接口板又称为网络接口NIC(NetworkInterfaceCard)或简称为“网卡”。由于较新的计算机主板上已经嵌入了这种适配器,不使用单独的网卡了,因此…

发表回复

您的电子邮箱地址不会被公开。

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