ES6技巧和窍门,使您的代码更简洁,更短且更易于阅读!

by Sam Williams

通过山姆·威廉姆斯

ES6技巧和窍门,使您的代码更简洁,更短且更易于阅读! (ES6 tips and tricks to make your code cleaner, shorter, and easier to read!)

模板文字 (Template literals)

Template literals make working with strings so much easier than before. They're started with a back tick, and can have variables inserted using ${variable}. Compare these two lines of code:

模板文字使使用字符串变得比以前容易得多。 它们以反斜线开头,可以使用${variable}插入${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 }.`;

This makes life far simpler and code easier to read. You can put anything inside of the curly braces: variables, equations, or function calls. I'll use these in examples throughout this article.

这使生活变得更加简单,代码也更易于阅读。 您可以在花括号内放置任何内容:变量,方程式或函数调用。 在本文的示例中,我将使用它们。

语法块作用域 (Syntax Block scoping)

JavaScript has always been scoped by functions, which is why it had become common to wrap the whole of a JavaScript file in an empty immediately invoked function expression (IIFE). This is done to isolate all of the variables in the file, so there are no variable conflicts.

JavaScript始终受函数范围限制,这就是为什么将整个JavaScript文件包装在一个空的立即调用函数表达式(IIFE)中变得很普遍的原因。 这样做是为了隔离文件中的所有变量,因此没有变量冲突。

Now, we have block scoping and two new variable declarations which are bound to a block.

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

“让”宣言 (‘Let’ Declaration)

This is similar to var but has a few notable differences. Because it's block scoped, a new variable with the same name can be declared without affecting outer variables.

这类似于var但有一些显着差异。 因为它是块作用域的,所以可以声明一个具有相同名称的新变量而不会影响外部变量。

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

Because its bound to a block scope, it solves this classic interview question:"what is output, and how would you get it to work as you expect?"

因为它受限制于范围,所以它解决了这个经典的采访问题:“输出了什么,您将如何使其按预期工作?”

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

In this case it outputs "5 5 5 5 5" because the variable i changes on each iteration.

在这种情况下,它输出“ 5 5 5 5 5”,因为变量i在每次迭代中都会更改。

If you switch out the var for let then everything changes. Now, each loop creates a new block scope with the value for i bound to that loop. It is though you've written:

如果您将var切换为let那么一切都会改变。 现在,每个循环都将创建一个新的块范围,并为该循环绑定i的值。 尽管您已经写过:

{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)}

Another difference between var and let is that let isn't hoisted as var is.

varlet之间的另一个区别是let不会像var那样悬挂。

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

Because of its tighter scoping and more predictable behaviour, some people have said that you should use let instead of var, except where you specifically need the hoisting or looser scoping of the var declaration.

由于它的作用域范围更窄且行为更可预测,因此有人说您应该使用let而不是var ,除非您特别需要var声明的提升或宽松作用域。

康斯特 (Const)

If you wanted to declare a constant variable in JavaScript before, it was convention to name the variable in block caps. However, this wouldn’t secure the variable — it just let other developers know that it was a constant and shouldn't be changed.

如果您以前想在JavaScript中声明一个常量,则习惯上以大写字母命名该变量。 但是,这不能保证变量的安全-它只是让其他开发人员知道它是一个常量,因此不应更改。

Now we have the const declaration.

现在我们有了const声明。

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

const doesn't make the variable immutable, just locks its assignment. If you have a complex assignment (object or array), then the value can still be modified.

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'}}

块作用域作用域问题 (Problem with block scoping functions)

Function declarations are now specified to be bound to block scoping.

现在将函数声明指定为绑定块作用域。

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

The problem comes when you declare a function inside an if statement.

当您在if语句中声明一个函数时,就会出现问题。

Consider this:

考虑一下:

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

Before ES6, both function declarations would have been hoisted and the result would have been 'I didn\'t pass' no matter what something was. Now we get 'ReferenceError', as baz is always bound by the block scope.

在ES6之前,无论什么something ,两个函数声明都会被吊起,结果将是'I didn\'t pass' 。 现在我们得到'ReferenceError' ,因为baz始终受块作用域的约束。

传播 (Spread)

ES6 introduces the ... operator, which is referred to as the ‘spread operator’. It has two main uses: spreading an array or object into a new array or object, and joining multiple parameters into an array.

ES6引入了...运算符,该运算符称为“扩展运算符”。 它有两个主要用途:将数组或对象散布到新的数组或对象中,以及将多个参数连接到数组中。

The first use case is the one you'll probably encounter most, so we’ll look at that first.

第一个用例是您可能会遇到最多的用例,因此我们将首先看一下。

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

An object can also be spread, inputting each of the key value pairs into the new object. ( Object spread is actually in stage 4 of proposal and will be officially in ES2018. Its only supported by Chrome 60 or later, Firefox 55 or later, and Node 6.4.0 or later)

还可以传播对象,将每个键值对输入到新对象中。 (对象传播实际上处于提案的第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}

Another feature of the spread operator is that it creates a new array or object. The example below creates a new array for b, but c just refers to the same array.

散布运算符的另一个功能是它创建一个新的数组或对象。 下面的示例为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 arraysc.push(5);console.log(a);  // [1, 2, 3, 5] console.log(c);  // [1, 2, 3, 5] referencing the same array

The second use case is gathering variables together into an array. This is very useful for when you don’t know how many variables are being passed to a function.

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

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

默认参数 (Default Parameters)

Functions can now be defined with default parameters. Missing or undefined values are initialized with the default value. Just be careful — because null and false values are coerced to 0.

现在可以使用默认参数定义功能。 缺少或未定义的值将使用默认值初始化。 请注意,因为null和false值被强制为0。

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

The default values can be more than just values — they can also be expressions or functions.

默认值不仅可以是值,还可以是表达式或函数。

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 ]

解构 (Destructuring)

Destructuring is the process of taking apart the array or object on the left hand side of the equal sign. The array or object can come from a variable, function, or equation.

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

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

With object destructuring, the keys of the object can be listed inside curly braces to extract that key-value pair.

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

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

Sometimes, you want to extract the values but assign them to a new variable. This is done using a 'key: variable' pairing on the left of the equals sign.

有时,您想提取值,但将其分配给新变量。 这是使用等号左侧的“ 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.

Another thing that object destructuring allows is assigning a value to multiple variables.

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

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

对象文字和简明参数 (Object Literals and Concise Parameters)

When you are creating an object literal from variables, ES6 allows you to omit the key if it is the same as the variable name.

通过变量创建对象文字时,如果ES6与变量名称相同,则ES6允许您省略该键。

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}

This can also be used in combination with destructuring to make your code much simpler and cleaner.

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

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

It can also be used to destructure objects passed into functions. Method 1 and 2 are how you would have done it before ES6, and method 3 uses destructuring and concise parameters.

它也可以用来解构传递给函数的对象。 方法1和2是在ES6之前的操作方式,方法3使用了结构分解和简洁的参数。

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

Using ES6, we can extract the age, name and company without extra variable declaration.

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

动态属性名称 (Dynamic Property Names)

ES6 adds the ability to create or add properties with dynamically assigned keys.

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

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

箭头功能 (Arrow Functions)

Arrow functions have two main aspects: their structure and their this binding.

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

They can have a much simpler structure than traditional functions because they don't need the function key word, and they automatically return whatever is after the arrow.

与传统函数相比,它们的结构要简单得多,因为它们不需要function关键字,并且它们会自动返回箭头后面的内容。

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

If the function requires more than a simple calculation, curly braces can be used and the function returns whatever is returned from the block scope.

如果函数需要的不仅仅是简单的计算,则可以使用花括号,并且函数将返回从块范围返回的所有内容。

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}`;}

One of the most useful places for arrow functions is in array functions like .map, .forEach or .sort.

箭头函数最有用的地方之一是数组函数,例如.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' ]

As well as having a shorter syntax, it also fixes the issues that often arose around the this binding behaviour. The fix with pre-ES6 functions was to store the this reference, often as a self variable.

除了具有较短的语法外,它还解决了this绑定行为经常出现的问题。 ES6之前的功能的解决方法是将this引用存储为一个self变量。

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

This had to be done because the this binding is dynamic. This means that the this inside the event listener and the this inside the doSomething do not refer to the same thing.

之所以必须这样做,是因为this绑定是动态的。 这意味着, this事件监听器内, this里面doSomething没有提到同样的事情。

Inside arrow functions, the this binding is lexical, not dynamic. This was the main design feature of the arrow function.

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

Whilst lexical this binding can be great, sometimes that's not what is wanted.

虽然在词法上this绑定可能很棒,但有时并不是想要的。

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

When we use a.oneThing(6), the this.otherThing( b ) reference fails as this doesn't point to the a object, but to the surrounding scope. If you are rewriting legacy code using ES6 syntax, this is something to watch out for.

当我们使用a.oneThing(6)所述this.otherThing( b )引用作为失败this点不至a物体,但对周围的范围。 如果要使用ES6语法重写旧代码,则需要提防这一点。

for … of循环 (for … of Loops)

ES6 adds a way to iterate over each of the values in an array. This is different from the existing for ... in loop that loops over the key/index.

ES6添加了一种遍历数组中每个值的方法。 这与现有的for ... in循环不同,该循环在键/索引上循环。

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

Using the new for … of loop saves adding a let val = a[idx] inside each loop.

使用新的for … of循环可节省在每个循环内添加let val = a[idx]

Arrays, strings, generators and collections are all iterable in standard JavaScript. Plain objects can't normally be iterated over, unless you have defined an iterator for it.

数组,字符串,生成器和集合都可以在标准JavaScript中进行迭代。 普通对象通常不能被迭代,除非您已为其定义了迭代器。

数字字面量 (Number Literals)

ES5 code handled decimal and hexadecimal number formats well, but octal form wasn't specified. In fact, it was actively disallowed in strict mode.

ES5代码可以很好地处理十进制和十六进制数字格式,但是未指定八进制形式。 实际上,在严格模式下它是积极禁止的。

ES6 has added a new format, adding an o after the initial 0 to declare the number an octal. They've also added a binary format.

ES6添加了一种新格式,在初始0后面添加一个o ,以将该数字声明为八进制。 他们还添加了二进制格式。

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

以及更多… (And Much More…)

There is much, much more that ES6 offers us to make our code cleaner, shorter, easier to read and more robust. I aim to write a continuation of this article covering the less well known bits of ES6.

ES6为我们提供了许多更多功能,以使我们的代码更简洁,更短,更易于阅读且更强大。 我打算写这篇文章的续篇,内容涉及ES6不太为人所知的部分。

If you can’t wait that long, have a read of Kyle Simpson’s You Don’t Know JS book on ES6, or check out this brilliant little website!

如果您不能等那么久,请阅读Kyle Simpson的ES6上的“ You Do n't Know JS”一书 ,或者访问这个出色的小网站

Do you want to become a developer and get your first software job? Download the 7 Steps to Becoming a Developer and Getting Your First Job.

您想成为一名开发人员并获得第一份软件工作吗? 下载成为开发人员并获得第一份工作7个步骤

NEXT -&gt; How to Secure Your Dream Job. Master the Interview Process

下一步-&g t; 如何确保梦想中的工作。 掌握面试过程

If you liked this and found it helpful, show your support by clapping away and subscribe to get more articles like this one!

如果您喜欢它并觉得有帮助,请鼓掌表示支持并订阅,以获取更多类似此文章的文章!

翻译自: https://www.freecodecamp.org/news/make-your-code-cleaner-shorter-and-easier-to-read-es6-tips-and-tricks-afd4ce25977c/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值