ES6 中的一些技巧,使你的代码更清晰,更简短,更易读!

更新日期: 2018-05-22阅读: 2.6k标签: es6

模版字符串

模板模版字符串使得字符串拼接比以前更容易。 它以反向标记(Tab 正上方那个字符)开始,并且可以使用${variable}插入变量。 比较以下两行代码

var fName = 'Peter', sName = 'Smith', age = 43, job = 'photographer';
var a = 'Hi, I\'m ' + fName + ' ' + sName + ', I\'m ' + age + ' and work as a ' + job + '.';
var b = `Hi, I'm ${ fName } ${ sName }, I'm ${ age } and work as a ${ job }.`;

这会让一切变的更简单,代码更易于阅读。 你可以将任何内容放入花括号中:变量,方程式或函数调用。 我将在整篇文章的示例中使用它们。


块级作用域

JavaScript 本身一直是函数式作用域,这就是我们经常将整个 JavaScript 文件封装在一个空的立即调用函数表达式(IIFE)中的原因。这样做是为了隔离文件中的所有变量,因此全局中就不会存在变量名冲突。

现在,我们有块级作用域和两个绑定到块的新变量声明。


Let

这与var类似,但有一些显着差异。由于它声明的变量具有块级作用域,所以可以在不影响外部变量的情况下声明具有相同名称的新局部(内部)变量。

var a = 'car' ;
{
    let a = 5;
    console.log(a) // 5
}
console.log(a) // car

因为它绑定到一个块(即就是 { 和 } 之间的范围),它解决了这个经典的面试问题:“输出是什么,如何让它按照你的期望工作?”

for (var i = 1; i < 5; i++){
    setTimeout(() => { console.log(i); }, 1000);
}

在这种情况下,它会输出 “5 5 5 5 5”,因为变量 i 在每次迭代中都会被改变,最终所有结果以最后一次变更为准。

如果您将var切换为let,那就不一样了。现在,每个循环都会创建一个新的块作用域,其值为绑定到该循环的值。相当于你写了:

{let i = 1; setTimeout(() => { console.log(i) }, 1000)}
{let i = 2; setTimeout(() => { console.log(i) }, 1000)}
{let i = 3; setTimeout(() => { console.log(i) }, 1000)}
{let i = 4; setTimeout(() => { console.log(i) }, 1000)}
{let i = 5; setTimeout(() => { console.log(i) }, 1000)

var和let之间的另一个区别是let不会像var一样被提升。

{
    console.log(a); // undefined
    console.log(b); // ReferenceError
    var a = 'car';
    let b = 5;
}

由于其更严格的范围界定和更可预测的行为,有些人表示应该使用let而不是var,除非特别需要用var的声明提升或需要其更宽松的作用范围。


Const

如果你想在 JavaScript 中声明一个常量变量,那么惯例是将变量命名大写。然而,这并不能保证它是一个常量 - 它只是让其他开发人员知道这是一个常量,不应该改变。

现在我们有了const声明。

{
    const c = "tree";
    console.log(c);  // tree
    c = 46;  // TypeError!
}

const 不会使变量不可变,只是锁定它的赋值。 如果你有一个复杂的赋值(对象或数组),那么该值仍然可以修改。

{
    const d = [1, 2, 3, 4];
    const dave = { name: 'David Jones', age: 32};
    d.push(5);
    dave.job = "salesman";
    console.log(d);  // [1, 2, 3, 4, 5]
    console.log(dave);  // { age: 32, job: "salesman", name: 'David Jones'}
}


块级作用域函数问题

函数声明现在被指定为必须绑定到块级作用域。

{
    bar(); // works
    function bar() { /* do something */ }
}
bar();  // doesn't work

当你在if语句中声明一个函数时,问题就来了。考虑这个:

if ( something) {
    function baz() { console.log('I passed') }
} else {
    function baz() { console.log('I didn\'t pass') }
}
baz();

在 ES6 之前,这两个函数声明都会被提升,结果就是 ‘I didn\’t pass’,不管something 是什么东西。

现在我们会得到 ‘ReferenceError’,因为baz()总是受到块范围的约束。


扩展运算符

ES6 引入了...运算符,它被称为“扩展运算符”。 它有两个主要用途:将数组或对象分散到新的数组或对象中,并将多个参数合并到一个数组中。

第一个用例是你可能遇到的最多的用例,所以我们先看看。

let a = [3, 4, 5];
let b = [1, 2, ...a, 6];
console.log(b);  // [1, 2, 3, 4, 5, 6]
This can be very useful for passing in a set of variables to a function from an array.
function foo(a, b, c) { console.log(`a=${a}, b=${b}, c=${c}`)}
let data = [5, 15, 2];
foo( ...data); // a=5, b=15, c=2

也可以扩展对象,将每个键值对输入到新对象中。(实际上是在提案的第 4 阶段,并将在 ES2018 中正式推出,仅支持 Chrome 60 或更高版本,Firefox 55 或更高版本以及 Node 6.4.0 或更高版本)

let car = { type: 'vehicle ', wheels: 4};
let fordGt = { make: 'Ford', ...car, model: 'GT'};
console.log(fordGt); // {make: 'Ford', model: 'GT', type: 'vehicle', wheels: 4}

... 运算符的另一个特点是它创建一个新的数组或对象。 下面的例子为 b 创建了一个新的数组,但 c 只是指向同一个数组。

let a = [1, 2, 3];
let b = [ ...a ];
let c = a;
b.push(4);
console.log(a);  // [1, 2, 3]
console.log(b);  // [1, 2, 3, 4] referencing different arrays
c.push(5);
console.log(a);  // [1, 2, 3, 5]
console.log(c);  // [1, 2, 3, 5] referencing the same array

第二个例子是将变量一起收集到一个数组中。 当你不知道有多少变量传递给函数时,这非常有用。

function foo(...args) {
    console.log(args);
}
foo( 'car', 54, 'tree');  //  [ 'car', 54, 'tree' ]


函数默认参数

现在可以使用默认参数定义函数。缺少或未定义的值将使用默认值进行初始化。只要小心 - 因为空值和假值会被强制为0。

function foo( a = 5, b = 10) {
    console.log( a + b);
}
foo();  // 15
foo( 7, 12 );  // 19
foo( undefined, 8 ); // 13
foo( 8 ); // 18
foo( null ); // 10 as null is coerced to 0

默认值可以不仅仅是值 - 它们也可以是表达式或函数。

function foo( a ) { return a * 4; }
function bar( x = 2, y = x + 4, z = foo(x)) {
    console.log([ x, y, z ]);
}
bar();  // [ 2, 6, 8 ]
bar( 1, 2, 3 ); //[ 1, 2, 3 ]
bar( 10, undefined, 3 );  // [ 10, 14, 3 ]


解构

解构是拆分等号左侧的数组或对象的过程。数组或对象可以来自变量,函数或等式。

let [ a, b, c ] = [ 6, 2, 9];
console.log(`a=${a}, b=${b}, c=${c}`); //a=6, b=2, c=9
function foo() { return ['car', 'dog', 6 ]; }
let [ x, y, z ] = foo();
console.log(`x=${x}, y=${y}, z=${z}`);  // x=car, y=dog, z=6

通过对象解构,可以在大括号内列出对象的键以提取该键值对。

function bar() { return {a: 1, b: 2, c: 3}; }
let { a, c } = bar();
console.log(a); // 1
console.log(c); // 3
console.log(b); // undefined

有时,你想取值,将它们分配给一个新的变量。 这是通过在等号左边的 key: variable 配对完成的。

function baz() {
    return {
        x: 'car',
        y: 'London',
        z: { name: 'John', age: 21}
    };
}
let { x: vehicle, y: city, z: { name: driver } } = baz();
console.log(
    `I'm going to ${city} with ${driver} in their ${vehicle}.`
); // I'm going to London with John in their car.

对象解构允许的另一件事是为多个变量赋值。

let { x: first, x: second } = { x: 4 };
console.log( first, second ); // 4, 4


对象字面量和简明参数

当您从变量创建对象字面量时,ES6 允许您在与 key 与变量名称相同的情况下省略 key 名。

let a = 4, b = 7;
let c = { a: a, b: b };
let concise = { a, b };
console.log(c, concise) // {a: 4, b: 7}, {a: 4, b: 7}

这也可以与解构结合使用,使你的代码更简单,更清洁。

function foo() {
    return {
        name: 'Anna',
        age: 56,
       job: { company: 'Tesco', title: 'Manager' }
    };
}
// pre ES6
let a = foo(), name = a.name, age = a.age, company = a.job.company;
// ES6 destructuring and concise parameters
let { name, age, job: {company}} = foo();

它也可以用来解构对象传递给函数。方法 1 和 2 是你在 ES6 之前完成它的方法,方法 3 使用解构和简明的参数。

let person = {
    name: 'Anna',
    age: 56,
    job: { company: 'Tesco', title: 'Manager' }
};
// method 1
function old1(person) {
    var yearOfBirth = 2018 - person.age;
    console.log( `${ person.name } works at ${ person.job.company } and was born in ${ yearOfBirth }.`);
}
// method 2
function old1(person) {
    var age = person.age,
        yearOfBirth = 2018 - age,
        name = person.name,
        company = person.job.company;
    console.log( `${ name } works at ${ company } and was born in ${ yearOfBirth }.`);
}
// method 3
function es6({ age, name, job: {company}}) {
    var yearOfBirth = 2018 - age;
    console.log( `${ name } works at ${ company } and was born in ${ yearOfBirth }.`);
}

使用 ES6,我们可以提取age,name和company而无需额外的变量声明。


动态属性名称

ES6 添加了使用动态分配的 key 创建或添加属性的功能。

let  city= 'sheffield_';
let a = {
    [ city + 'population' ]: 350000
};
a[ city + 'county' ] = 'South Yorkshire';
console.log(a); // {sheffield_population: 350000, sheffield_county: 'South Yorkshire' }


箭头函数

箭头函数有两个主要方面:结构和this绑定。

它们可以具有比传统功能更简单的结构,因为它们不需要功能关键字,并且它们自动返回箭头之后的任何内容。

var foo = function( a, b ) {
    return a * b;
}
let bar = ( a, b ) => a * b;

如果函数需要的不仅仅是一个简单的计算,可以使用大括号,并且该函数会返回花括号块范围返回的任何内容。

let baz = ( c, d ) => {
    let length = c.length + d.toString().length;
    let e = c.join(', ');
    return `${e} and there is a total length of  ${length}`;
}

对于箭头函数最有用的地方之一是在map(),forEach()或sort()之类的数组函数中。

let arr = [ 5, 6, 7, 8, 'a' ];
let b = arr.map( item => item + 3 );
console.log(b); // [ 8, 9, 10, 11, 'a3' ]

除了具有更短的语法外,它还修复了在绑定行为经常出现的问题。具有 ES6 之前的功能的修复是将this引用存储,通常作为自变量存储。

var clickController = {
    doSomething: function (..) {
        var self = this;
        btn.addEventListener(
            'click',
            function() { self.doSomething(..) },
            False
       );
   }
};

这必须做到,因为这个绑定是动态的。 这意味着这个事件监听器里面的这个和doSomething里面的这个不是指同一个事物。

在箭头函数里,这个绑定是词法的,而不是动态的。 这是箭头功能的主要设计特征。

虽然这种绑定可能是伟大的,有时这不是想要的。

let a = {
    oneThing: ( a ) => {
         let b = a * 2;
         this.otherThing(b);
    },
    otherThing: ( b ) => {....}
};
a.oneThing(6);

当我们使用a.oneThing(6)时,this.otherThing(b)引用失败,因为这不是指向一个对象,而是指向周围的作用域。 如果您使用 ES6 语法重写遗留代码,则需要注意这一点。


for … of 循环

ES6 增加了一种迭代数组中每个值的方法。 这与现有的 ... in 不同,它循环使用key/index。

let a = ['a', 'b', 'c', 'd' ];
// ES6
for ( var val of a ) {
    console.log( val );
} // "a" "b" "c" "d"
// pre-ES6
for ( var idx in a ) {
    console.log( idx );
}  // 0 1 2 3

使用新的for ... of循环,不必在在每个循环内添加一个let val = a[idx]。

数组,字符串,生成器和集合都可以在标准 JavaScript 中迭代。普通对象通常不能迭代,除非你已经为它定义了一个迭代器(Iterator)。


数字字面量

ES5 代码很好地处理了十进制和十六进制数字格式,但未指定八进制格式。事实上,它在严格的模式下被禁止。

ES6添加了一种新格式,在最初的 0 之后添加一个 o (注意是字母)以将该数字声明为八进制数。ES6 还添加了二进制格式。

Number( 29 )  // 29
Number( 035 ) // 35 in old octal form.
Number( 0o35 ) // 29 in new octal form
Number( 0x1d ) // 29 in hexadecimal
Number( 0b11101 ) // 29 in binary form


还有很多。。。

ES6 为我们提供了更多的功能,使我们的代码更简洁,更短,更易于阅读和更强大。 我的目标是撰写本文的续篇,内容涵盖了 ES6 中不太知名的部分。


原文地址:https://medium.freecodecamp.org/make-your-code-cleaner-shorter-and-easier-to-read-es6-tips-and-tricks-afd4ce25977c
更多内容请见译者 Blog:https://github.com/elevenbeans/elevenbeans.github.io  


链接: https://fly63.com/article/detial/800

es6 箭头函数的使用总结,带你深入理解js中的箭头函数

箭头函数是ES6中非常重要的性特性。它最显著的作用就是:更简短的函数,并且不绑定this,arguments等属性,它的this永远指向其上下文的 this。它最适合用于非方法函数,并且它们不能用作构造函数。

详解JavaScript模块化开发require.js

js模块化的开发并不是随心所欲的,为了便于他人的使用和交流,需要遵循一定的规范。目前,通行的js模块规范主要有两种:CommonJS和AMD

js解构赋值,关于es6中的解构赋值的用途总结

ES6中添加了一个新属性解构,允许你使用类似数组或对象字面量的语法将数组和对象的属性赋给各种变量。用途:交换变量的值、从函数返回多个值、函数参数的定义、提取JSON数据、函数参数的默认值...

ES6中let变量的特点,使用let声明总汇

ES6中let变量的特点:1.let声明变量存在块级作用域,2.let不能先使用再声明3.暂时性死区,在代码块内使用let命令声明变量之前,该变量都是不可用的,4.不允许重复声明

ES6的7个实用技巧

ES6的7个实用技巧包括:1交换元素,2 调试,3 单条语句,4 数组拼接,5 制作副本,6 命名参数,7 Async/Await结合数组解构

ES6 Decorator_js中的装饰器函数

ES6装饰器(Decorator)是一个函数,用来修改类的行为 在设计阶段可以对类和属性进行注释和修改。从本质上上讲,装饰器的最大作用是修改预定义好的逻辑,或者给各种结构添加一些元数据。

基于ES6的tinyJquery

Query作为曾经Web前端的必备利器,随着MVVM框架的兴起,如今已稍显没落。用ES6写了一个基于class简化版的jQuery,包含基础DOM操作,支持链式操作...

Rest/Spread 属性_探索 ES2018 和 ES2019

Rest/Spread 属性:rest操作符在对象解构中的使用。目前,该操作符仅适用于数组解构和参数定义。spread操作符在对象字面量中的使用。目前,这个操作符只能在数组字面量和函数以及方法调用中使用。

使用ES6让你的React代码提升到一个新档次

ES6使您的代码更具表现力和可读性。而且它与React完美配合!现在您已了解更多基础知识:现在是时候将你的ES6技能提升到一个新的水平!嵌套props解构、 传下所有props、props解构、作为参数的函数、列表解构

在使用es6语法class的时候,babel到底做了什么?

自从有了webpack之后,我们这些jscoder似乎得到了前所未有的解放,箭头函数,对象解构,let,const关键字,以及class、extends等等,webpack会帮我们把这些es6代码转换成浏览器能够识别的es5代码,那么有多少人真正的看过,babel转换之后的代码呢?

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!