应该在项目中用起来的 ES6 语法(一)

学习过 ES 6 有一段时间了,也在现有的项目中投入了使用,新的语法让代码的可读性大大提高,这对项目的可维护性是至关重要的,在这里记录下一些在实战项目中比较常用的语法,以及新语法对旧语法的对比。

干净的作用域 let, const 和 {}

以往写 JS 最怕的就是变量污染了,当项目太大,var声明的变量到处都是,重复声明 console 没有报错,很不好调试,有了letconst,当你变量重复声明或者犯了其他错误时,console 都会报错,让代码更加规范:

1. 用const声明一个常量

const URL = 'http://www.google.com'; // 不再变化,尝试修改它会报错

// 旧的写法
var URL = 'http://www.google.com'; // 修改不会报错

2. 用 let 解决 for 循环索引变化的问题

// 循环结束`i`被垃圾回收,`i`只在循环体中生效
for (let i = 0; i < 6; i++) {
    // do something
}
console.log(i); // undefined 

// 旧的写法,循环结束后`i`的值为 5,这并不是我们期望的
for (var i = 0; i < 6; i++) {
    // do something
}
console.log(i); // 5

3. 用{}替换难以理解的闭包作用域

{
    // do someting
}

// 旧的写法(IIFE写法),对新手来说这个语法很不友好
(function() {
    // do someting
}());

注意:大部分场景使用的还是const,而不是let

JS 的 const 和其他语言有点小区别,当我们定义的变量后续不会再改变的时候,我们就应该使用const,只有明确了变量会改变,才会使用let

// 定义一个常量
const URL = 'http://www.jianshu.com/api/posts/id';

// 获取一个 dom 元素
const $modal = $('.modal'); 

// 定义一个书的实体,即使你修改了书的属性,也是用 const
const book = {};
book.title = '围城';
book.author = '钱钟书';

// webpack 引入一个模块
const vue = require('vue');

快速提取参数,变量解构赋值

解构可以理解为从指定的数组或者对象中提取数组元素或者对象属性的值,然后赋值到指定变量中:

1. 快速交换变量

// 交换`x`, `y`和`z`的值
let x = 1, y = 2, z = 3;
[x, y, z] = [z, x, y];
console.log(x, y, z); // 3 1 2

// 旧的写法
var x = 1, y = 2, z = 3;
var temp = x; // 临时变量
x = z;
z = y;
y = temp;
console.log(x, y, z); // 3 1 2

2. 定义函数默认值

let fn = function({
        foo = 1,
        bar = 'foo',
        hello = false
    }) {
    console.log(foo, bar, hello);
};
fn(); // 1, foo, false

// 旧的写法
let fn = function(foo, bar, hello) {
    var foo = foo || 1;
    var bar = bar || 'foo';
    var hello = hello || false;

    console.log(foo, bar, hello);
};
fn(); // 1, foo, false

3. 快速提取模块中的子模块

// ES 6 的模块语法
import {selector, spinner} from 'Bootstrap.js'
// require.js
const { SourceMapConsumer, SourceNode } = require("source-map");

4. 遍历时快速提取变量

const books = [{
    title: '围城', 
    author: '钱钟书',
}, {
    title: '三国演义',
    author: '罗贯中'
}];

{ title, author } 相当于一个 `book` 变量
books.map(({ title, author }) => console.log(title, author));

// 旧的写法
books.map(function(book) {
    console.log(book.title, book.author); 
});

很有用的字符串扩展

JS 的字符串函数一直都是残缺不齐的,一个indexOf用来做了太多的功能,而 ES 6 提供了很多语义化的函数来方便开发:

1. 便捷函数includes(), startsWith(), endsWith()

// 这三个函数都返回布尔值,不需要再去繁琐的判断`indexOf`返回的数值了
'hello world'.includes('wor'); // true
'hello world'.startsWith('he'); // true
'hello world'.endsWith('he'); // false

// 旧的写法,代替语意不明确的indexOf
'hello world'.indexOf('wor') !== -1;

2. 模板字符串,漂亮的写法

新的模板字符串``可以使 html 片段的引入更加美观与规范,嵌入的变量名的形式为${var},大括号中支持js的语法,非常实用:

const basket = { count: 1, onSale: 'iPhone' };

// 模板字符串,空格和缩进都会留着,即保留格式
$('#result').append(`
    There are <b>${basket.count}</b> items
    in your basket, <em>${basket.onSale}</em> // 这里替换为变量的值
    are on sale!
    <p>${basket.count + basket.add}</p>
`);

// 旧的写法
$('#result').append(
    'There are <b>' + basket.count + '</b> ' +
    'items in your basket, ' +
    '<em>' + basket.onSale +
    '</em> are on sale!'
);

在模板字符串中使用函数

const books = [{
    title: '围城', 
    author: '钱钟书',
}, {
    title: '三国演义',
    author: '罗贯中'
}];

const html = `
    <ul>
        ${ books.map(book => 
        `<li>
            <div>${ book.title }</div>
            <div>${ book.author }</div>
        </li>`
        ).join('') }
    </ul>
`
console.log(html)
/** 
    <ul>
        <li>
            <div>围城</div>
            <div>钱钟书</div>
        </li><li>
            <div>三国演义</div>
            <div>罗贯中</div>
        </li>
    </ul>
*/

注意:使用模板字符串要注意防止 XSS 攻击

function escapeHtml(text) {
    var map = {
        '&': '&',
        '<': '<',
        '>': '>',
        '"': '"',
        "'": '''
  };

  return text.replace(/[&<>"']/g, function(m) { return map[m]; });
}

const html = `${escapeHtml(user_input)}`;

告别不严谨的 Number 类型判断

1. Number.isFinite(), Number.isNaN(), Number.isInteger()

JS 一直有个让人诟病的地方,就是类型不够严谨,就连在类型判断上都太过于灵活,新的几个函数轻松解决这些问题,再也不用觉得 Number 类型不够好了:

// 判断是否为有限数值
Number.isFinite(7); // true
Number.isFinite(Infinity); // false
Number.isFinite(-Infinity); // false

// 判断是否为 NaN 类型
Number.isNaN(NaN) // true

// 判断是否为整数
Number.isInteger(25) // true

2. 常用的数学函数,取整,判断正负

// 去除小数部分,返回整数部分
Math.trunc(5.333); // 5

// 判断是否为正数,负数,0
// 参数为正数,返回+1;
// 参数为负数,返回-1;
// 参数为0,返回0;
// 参数为-0,返回-0;
// 其他值,返回NaN。
Math.sign(-5) // -1

对不好用的数组说再见

1. 用Array.from()将类似数组的对象转换为数组

// 转换arguments
const fn = function() {
    const args = Array.from(arguments);
    args.forEach((arg) => console.log(arg)); // 数组才能用 forEach 等方法
}

// 转换 原生 dom 返回的 NodeList
const lis = document.querySelectorAll('li');
const arrLis = Array.from(lis);
arrLis.forEach((li) => console.log(li)); // 数组才能用 forEach 等方法

// 使用拓展符也可以达到这种效果
const fn = function() {
    const args = [...arguments];
    args.forEach((arg) => console.log(arg)); // 数组才能用 forEach 等方法
}
// 转换NodeList
const arrLis = [...document.querySelectorAll('li')];
arrLis.forEach((li) => console.log(li)); // 数组才能用 forEach 等方法

2. Array.of()快速组合数组

const x = 'wynne', y = 'zheng';
console.log(Array.of(x, y)); // ['wynne', 'zheng']

// 旧的写法
const x = 'wynne', y = 'zheng';
const arr = [x, y]; // ['wynne', 'zheng']

3. 超级实用的查找功能 find() & findIndex()includes()

1.find()可以通过回调函数进行数组筛选,返回该成员,而findIndex()返回索引

const books = [{
    title: '围城', 
    author: '钱钟书',
}, {
    title: '三国演义',
    author: '罗贯中'
}];
const item = books.find(({ title, author }) => title === '围城');
console.log(item); // { title: '围城', author: '钱钟书' }

// 旧的写法
var books = [{
    title: '围城', 
    author: '钱钟书',
}, {
    title: '三国演义',
    author: '罗贯中'
}];
var item = null;
books.forEach(function() {
    if (value > 3) {
        item = value;
        return;
    }
});
console.log(item); // { title: '围城', author: '钱钟书' }

2. 判断是否存在于数组中,用includes()代替语意差的indexOf

const books = [{
    title: '围城', 
    author: '钱钟书',
}, {
    title: '三国演义',
    author: '罗贯中'
}];
console.log(arr.includes( { title: '围城', author: '钱钟书' } ); // true

未完待续……

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,755评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,369评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,799评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,910评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,096评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,159评论 3 411
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,917评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,360评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,673评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,814评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,509评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,156评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,123评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,641评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,728评论 2 351

推荐阅读更多精彩内容