聊聊ES7和ES8的特性

本文对比展示了ES7和ES8中引入的新特性,包括includes()方法、指数操作符、Object.values()、Object.entries()、padStart()、padEnd()、Object.getOwnPropertyDescriptors()等,以及函数参数列表结尾允许逗号和Async/Await异步编程语法。

译者按: 转眼ES6发布2年了,是时候了解一下ES7ES8特性了!

为了保证可读性,本文采用意译而非直译,并且对源代码进行了大量修改。另外,本文版权归原作者所有,翻译仅用于学习。

我曾写过一篇关于ES6博客《10个最佳ES6特性》,这次我打算聊聊ES7ES8特性。

ES7只有2个特性:

ES8尚未发布(2017年1月),下面是它已经完成起草的一些特性:

Array.prototype.includes()

不使用ES7

使用indexOf()验证数组中是否存在某个元素,这时需要根据返回值是否为**-1**来判断:

let arr = ['react', 'angular', 'vue'];

if (arr.indexOf('react') !== -1)
{
    console.log('React存在');
}
使用ES7

使用includes()验证数组中是否存在某个元素,这样更加直观简单:

let arr = ['react', 'angular', 'vue'];

if (arr.includes('react'))
{
    console.log('React存在');
}

指数操作符

不使用ES7

使用自定义的递归函数calculateExponent或者Math.pow()进行指数运算:

function calculateExponent(base, exponent)
{
    if (exponent === 1)
    {
        return base;
    }
    else
    {
        return base * calculateExponent(base, exponent - 1);
    }
}

console.log(calculateExponent(7, 3)); // 输出343
console.log(Math.pow(7, 3)); // 输出343
使用ES7

使用指数运算符******,就像**+-**等操作符一样:

console.log(7**3);

Object.values()

不使用ES8

使用Object.keys()遍历对象的属性值,需要通过属性名key去获取属性值:

let obj = {a: 1, b: 2, c: 3};

Object.keys(obj).forEach((key) =>
{
    console.log(obj[key]); // 输出1, 2, 3
});
使用ES8

使用Object.values()遍历对象的属性值,无需使用使用属性名:

let obj = {a: 1, b: 2, c: 3}
Object.values(obj).forEach(value =>
{
    console.log(value); // 输出1, 2, 3
});

Object.entries()

不使用ES8

使用Object.keys()遍历对象的属性名和属性值:

let obj = {a: 1, b: 2, c: 3};

Object.keys(obj).forEach((key) =>
{
    console.log(key + ": " + obj[key]); // 输出a: 1, b: 2, c: 3
})
使用ES8

使用Object.entries()遍历对象的属性名和属性值:

let obj = {a: 1, b: 2, c: 3};

Object.entries(obj).forEach(([key, value]) =>
{
    console.log(key + ": " + value); // 输出a: 1, b: 2, c: 3
})

padStart()

不使用ES8
console.log('0.00')         	
console.log('10,000.00')    
console.log('250,000.00')  

输出结果如下:

0.00
10,000.00
250,000.00
使用ES8

使用padStart()可以在字符串前面填充指定的字符串:

console.log('0.00'.padStart(20))         	
console.log('10,000.00'.padStart(20))    
console.log('250,000.00'.padStart(20))    

输出结果如下:

                0.00
           10,000.00
          250,000.00

padEnd()

不使用ES8
console.log('0.00 ' + '0.00' )         	
console.log('10,000.00 ' + '10,000.00' )    
console.log('250,000.00 ' + '250,000.00')  

输出如下:

0.00 0.00
10,000.00 10,000.00
250,000.00 250,000.00
使用ES8

使用padEnd()可以在字符串后面填充指定的字符串:

console.log('0.00'.padEnd(20) + '0.00' )         	
console.log('10,000.00'.padEnd(20) + '10,000.00' )    
console.log('250,000.00'.padEnd(20) + '250,000.00')  

输出如下:

0.00                0.00
10,000.00           10,000.00
250,000.00          250,000.00

Object.getOwnPropertyDescriptors()

azatsBooks对象的定义如下:

let azatsBooks = {
    books: ['React Quickly'],
    get latest()
    {
        let numberOfBooks = this.books.length;
        if (numberOfBooks == 0) return undefined;
        return this.books[numberOfBooks - 1];
    }
};
不使用ES8

使用Object.getOwnPropertyDescriptor()获取单个属性的属性描述符。

获取azatsBooks对象的books属性的属性描述符:

console.log(Object.getOwnPropertyDescriptor(azatsBooks, 'books'));

/** 输出books属性的属性描述
[object Object] {
  configurable: true,
  enumerable: true,
  value: ["React Quickly"],
  writable: true
}
**/

获取azatsBooks对象的lastest方法的属性描述符:

console.log(Object.getOwnPropertyDescriptor(azatsBooks, 'latest'));

/** 输出lastest方法的属性描述
[object Object] {
  configurable: true,
  enumerable: true,
  get: function get latest() {
    let numberOfBooks = this.books.length
    if (numberOfBooks == 0) return undefined
    return this.books[numberOfBooks - 1]
  },
  set: undefined
}
**/
使用ES8

Object.getOwnPropertyDescriptors()相当于Object.getOwnPropertyDescriptor()的复数形式,可以获取对象的所有自身属性的描述符:

console.log(Object.getOwnPropertyDescriptors(azatsBooks))

/** 输出azatsBooks对象所有自身属性的属性描述
[object Object] {
  books: [object Object] {
    configurable: true,
    enumerable: true,
    value: ["React Quickly"],
    writable: true
  },
  latest: [object Object] {
    configurable: true,
    enumerable: true,
    get: function get latest() {
      let numberOfBooks = this.books.length
      if (numberOfBooks == 0) return undefined
      return this.books[numberOfBooks - 1]
    },
    set: undefined
  }
}
**/

函数参数列表结尾允许逗号

不使用ES8
var f = function(a,
  b,
  c,
  d // d之后不能带逗号
   ) { 
  console.log(d)
}
使用ES8
var f = function(a,
  b,
  c,
  d, // d之后允许带逗号
) { 
  console.log(d)
}

允许逗号之后,可以避免一些不必要的报错。(如果你希望实时监控JavaScript应用的错误,欢迎免费使用Fundebug)

Async/Await

使用Promise

使用Promise写异步代码,会比较麻烦:

axios.get(`/q?query=${query}`)
    .then(response => response.data)
    .then(data =>
    {
        this.props.processfetchedData(data);
    })
    .catch(error => console.log(error));
使用Async/Await

Async/Await使得异步代码看起来像同步代码,这正是它的魔力所在:

async fetchData(query) =>
{
    try
    {
        const response = await axios.get(`/q?query=${query}`);
        const data = response.data;
        return data;
    }
    catch (error)
    {
        console.log(error)
    }
}

fetchData(query).then(data =>
{
    this.props.processfetchedData(data)
})

Async/Await是写异步代码的新方式,以前的方法有回调函数Promise。相比于Promise,它更加简洁,并且处理错误、条件语句、中间值都更加方便,因此有望替代Promise,成为新一代的一步代码编写方式。对细节感兴趣的话,可以查看Fundebug翻译的《Async/Await替代Promise的6个理由》

关于Fundebug:

Fundebug专注于JavaScript、微信小程序、微信小游戏、支付宝小程序、React Native、Node.js和Java实时BUG监控。 自从2016年双十一正式上线,Fundebug累计处理了7亿+错误事件,得到了Google、360、金山软件、百姓网等众多知名用户的认可。欢迎免费试用!

版权声明

转载时请注明作者Fundebug以及本文地址: https://blog.fundebug.com/2017/08/28/es7-and-es8/

转载于:https://my.oschina.net/u/3375885/blog/2885200

<think>嗯,用户想让Spring Boot同时兼容Elasticsearch 78。这听起来有点挑战,因为不同版本的Elasticsearch客户端可能有兼容性问题。首先,我需要回忆一下Spring Data ElasticsearchElasticsearch客户端之间的关系。Spring Boot通常通过Spring Data Elasticsearch来整合Elasticsearch,而Spring Data Elasticsearch本身又依赖于Elasticsearch的Java客户端库。 Elasticsearch 78Java客户端之间可能存在API变化,特别是从78时,官方可能有重大更改。比如,High Level Client在7.x中被废弃,到了8.x可能完全移除,转而使用新的Java API Client。因此,直接让同一个应用同时支持两个大版本可能困难。 用户可能需要考虑多版本兼容的策略。比如,是否可以通过条件化配置来根据不同的环境加载不同的客户端实现?或者是否有第三方库可以帮助处理这种兼容性问题? 另外,Spring Data Elasticsearch的版本对应关系也很重要。比如,Spring Boot 2.7.x可能对应Spring Data Elasticsearch 4.4.x,支持Elasticsearch 7.x;而Spring Boot 3.x可能对应Spring Data Elasticsearch 5.x,支持Elasticsearch 8.x。如果用户的项目需要同时支持两者,可能需要维护不同版本的依赖,但这在同一个项目中可能会有冲突。 另一个可能性是使用Elasticsearch的Rest Client,通过HTTP请求而不是客户端库,这样可以减少版本依赖。但这样会失去Spring Data的Repository抽象带来的便利,需要手动处理请求响应。 此外,模块化项目结构可能也是一个方向,将不同版本的客户端隔离到不同的模块中,根据运行时环境动态加载。例如,使用Java的类加载机制或者OSGi,但这种方法可能复杂度过高,不适合大多数Spring Boot应用。 还需要考虑配置文件中的ES版本参数,可能通过配置属性来切换不同的客户端行为。例如,检查elasticsearch.version属性,然后初始化相应的客户端配置。但需要确保代码中没有使用版本特定的API,或者通过条件判断来避免调用不兼容的方法。 可能还需要处理依赖冲突,比如排除某些传递依赖,或者使用依赖管理来强制指定版本。例如,使用Maven的dependencyManagement或Gradle的resolutionStrategy来调整客户端库的版本。 最后,用户可能需要权衡维护多版本兼容的成本收益。如果确实需要同时支持ES7ES8,可能需要采用较为灵活的架构设计,或者推动升级到单一版本以减少复杂性。</think>要让Spring Boot同时兼容Elasticsearch 78,可以通过以下分层方案实现: ### 一、依赖隔离方案 1. **多模块项目结构** ```groovy // 主模块声明公共接口 implementation 'org.springframework.boot:spring-boot-starter-data-elasticsearch' // es7子模块 dependencies { implementation 'org.elasticsearch.client:elasticsearch-rest-high-level-client:7.17.3' } // es8子模块 dependencies { implementation 'co.elastic.clients:elasticsearch-java:8.2.3' implementation 'com.fasterxml.jackson.core:jackson-databind:2.12.3' } ``` 2. **动态类加载** 通过`URLClassLoader`隔离不同版本的客户端JAR包,避免类冲突[^1]。 ### 二、兼容层设计 ```java public interface ElasticsearchTemplate { @ConditionalOnProperty(name = "es.version", havingValue = "7") static class Es7Template implements ElasticsearchTemplate { // 使用RestHighLevelClient实现 } @ConditionalOnProperty(name = "es.version", havingValue = "8") static class Es8Template implements ElasticsearchTemplate { // 使用Java API Client实现 } } ``` 需统一封装CRUD操作接口,隐藏版本差异。 ### 三、配置策略 ```yaml # application-es7.yml elasticsearch: hosts: localhost:9200 version: 7 security: user: elastic password: changeme # application-es8.yml elasticsearch: hosts: localhost:9200 version: 8 api-key: ABCDEFG123456 ``` ### 四、注意事项 1. **文档类型处理**:ES8已移除`_doc`类型声明 2. **安全认证**:ES7使用basic auth,ES8推荐API key 3. **响应解析**:使用`JacksonParser`统一处理不同版本返回格式
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值