我的freeCodeCamp之旅Day---04

2019-01-03  本文已影响7人  TAsama

ES6:

1. var和let关键字之间的差异

使用var关键字声明变量的最大问题之一是可以在没有错误的情况下覆盖变量声明。

var camper = 'James';
var camper = 'David';
console.log(camper);

在ES6中引入了一个名为let的新关键字,用var关键字解决了这个潜在的问题。
如果要在上面代码的变量声明中用let替换var,结果将是一个错误。

let camper = 'James';
let camper = 'David'; // throws an error

2. 比较关键字var和let的范围

使用var关键字声明变量时,它将全局声明,如果在函数内声明,则声明为本地。
let关键字的行为类似,但具有一些额外的功能。
在块,语句或表达式中使用let关键字声明变量时,其范围仅限于该块,语句或表达式。
举个例子:

var printNumTwo;
for (var i = 0; i < 3; i++) {
  if(i === 2){
    printNumTwo = function() {
      return i;
    };
  }
}
console.log(printNumTwo());

此时,printNumTwo函数会返回3,由于i是一个由VAR声明的全局变量,导致在调用函数式取了全局i,经过for循环,此时的全局i已经是3了。
改成用let声明:

let printNumTwo;
for (let i = 0; i < 3; i++) {
  if (i === 2) {
    printNumTwo = function() {
      return i;
    };
  }
}
console.log(printNumTwo());
// returns 2
console.log(i);
// returns "i is not defined"

此时将返回2,且i变为undefined;
因为i是由let声明的,只在语句内有效。

3. 使用const关键字声明只读变量

let不是声明变量的唯一新方法。
在ES6中,您还可以使用const关键字声明变量。
const具有所有令人敬畏的功能,额外的好处是使用const声明的变量是只读的。
它们是一个常量值,这意味着一旦变量被赋值为const,就无法重新赋值。

4. 改变用const声明的数组

const声明在现代JavaScript中有许多用例。
一些开发人员更喜欢默认使用const分配所有变量,除非他们知道需要重新分配值。
只有在这种情况下,他们才会使用let。
但是,重要的是要理解使用const分配给变量的对象(包括数组和函数)仍然是可变的。

5. 防止对象突变

const声明本身并不能真正保护您的数据免受突变。
为确保您的数据不会发生变化,JavaScript提供了一个Object.freeze函数来防止数据突变。
对象冻结后,您将无法再从中添加,更新或删除属性。
任何更改对象的尝试都将被拒绝而不会出现错误。

let obj = {
  name:"FreeCodeCamp",
  review:"Awesome"
};
Object.freeze(obj);
obj.review = "bad"; //will be ignored. Mutation not allowed
obj.newProp = "Test"; // will be ignored. Mutation not allowed
console.log(obj); 
// { name: "FreeCodeCamp", review:"Awesome"}

对象被Object.freeze()函数冻结后,就无法对其内部进行任何修改了。

6. 使用箭头函数编写简明的匿名函数

在JavaScript中,我们通常不需要命名我们的函数,特别是在将函数作为参数传递给另一个函数时。
相反,我们创建内联函数。
我们不需要命名这些函数,因为我们不会在其他任何地方重用它们。
为此,我们经常使用以下语法:

const myFunc = function() {
  const myVar = "value";
  return myVar;
}

ES6为我们提供了语法糖,而不必以这种方式编写匿名函数。
相反,您可以使用箭头函数语法:

const myFunc = () => {
  const myVar = "value";
  return myVar;
}

当没有函数体,并且只有返回值时,箭头函数语法允许您省略关键字返回以及代码周围的括号。
这有助于将较小的函数简化为单行语句:

const myFunc = () => "value"

7. 用参数写箭头函数

就像普通函数一样,您可以将参数传递给箭头函数。

// doubles input value and returns it
const doubler = (item) => item * 2;

8. 编写高阶箭头函数

使用箭头函数语法计算数组realNumberArray中只有正整数(十进制数不是整数)的平方,并将新数组存储在变量squaredIntegers中。

const realNumberArray = [4, 5.6, -9.8, 3.14, 42, 6, 8.34, -2];
const squareList = (arr) => {
  "use strict";
  // change code below this line
  arr = arr.filter((element) => {
    return element > 0 && element % 1 == 0;
  }).map((element) => {
    return element * element;
  });
  const squaredIntegers = arr;
  // change code above this line
  return squaredIntegers;
};
// test your code
const squaredIntegers = squareList(realNumberArray);
console.log(squaredIntegers);
9. 设置函数的默认参数

为了帮助我们创建更灵活的函数,ES6引入了函数的默认参数。

function greeting(name = "Anonymous") {
  return "Hello " + name;
}
console.log(greeting("John")); // Hello John
console.log(greeting()); // Hello Anonymous

默认参数在未指定参数时启动(未定义)。
正如你在上面的示例中所看到的,当你未为参数提供值时,参数名称将接收其默认值“Anonymous”。
可以根据需要为任意数量的参数添加默认值。

10. 将Rest运算符与函数参数一起使用

为了帮助我们创建更灵活的函数,ES6为函数参数引入了Rest运算符。
使用rest运算符,您可以创建带有可变数量参数的函数。
这些参数存储在一个数组中,以后可以从函数内部访问。

function howMany(...args) {
  return "You have passed " + args.length + " arguments.";
}
console.log(howMany(0, 1, 2)); // You have passed 3 arguments
console.log(howMany("string", null, [1, 2, 3], { })); // You have passed 4 arguments.

Rest运算符消除了检查args数组的需要,并允许我们在参数数组上应用map(),filter()和reduce()。

11. 使用Spread运算符来就地赋值数组

ES6引入了Spread运算符,它允许我们在需要多个参数或元素的位置扩展数组和其他表达式。
下面的ES5代码使用apply()来计算数组中的最大值:

var arr = [6, 89, 3, 45];
var maximus = Math.max.apply(null, arr); // returns 89

扩展运算符使这种语法更易于阅读和维护.

const arr = [6, 89, 3, 45];
const maximus = Math.max(...arr); // returns 89

spread运算符将arr1的所有内容复制到另一个数组arr2中。

const arr1 = ['JAN', 'FEB', 'MAR', 'APR', 'MAY'];
let arr2;
(function() {
  "use strict";
  arr2 = [...arr1]; // change this line
})();
console.log(arr2);

12. 使用解构分配从对象分配变量

我们之前看到扩展运算符如何有效地扩展或解包数组的内容。
我们也可以用对象做类似的事情。
解构赋值是一种特殊的语法,用于将直接从对象获取的值整齐地分配给变量。

var voxel = {x: 3.6, y: 7.4, z: 6.54 };
const { x, y, z } = voxel; // x = 3.6, y = 7.4, z = 6.54

相反,如果你想将voxel.x的值存储到a中,将voxel.y存储到b中,将voxel.z存储到c中,那么你也可以这么做。

const { x : a, y : b, z : c } = voxel // a = 3.6, b = 7.4, c = 6.54

使用解构从输入对象AVG_TEMPERATURES获得明天的平均温度,并在明天将关键值赋值给tempOfTomorrow。

const AVG_TEMPERATURES = {
  today: 77.5,
  tomorrow: 79
};

function getTempOfTmrw(avgTemperatures) {
  "use strict";
  // change code below this line
  const {tomorrow: tempOfTomorrow} = avgTemperatures; // change this line
  // change code above this line
  return tempOfTomorrow;
}

console.log(getTempOfTmrw(AVG_TEMPERATURES)); // should be 79

13. 使用解构分配从嵌套对象分配变量

我们可以类似地将嵌套对象解构为变量。

const a = {
  start: { x: 5, y: 6},
  end: { x: 6, y: -9 }
};
const { start : { x: startX, y: startY }} = a;
console.log(startX, startY); // 5, 6

14. 使用解构分配从数组中分配变量

ES6使解构数组像解构对象一样简单。
扩展运算符和数组解构之间的一个关键区别是扩展运算符将数组的所有内容解包为逗号分隔列表。
因此,您无法选择或选择要分配给变量的元素。
我们还可以通过使用逗号来访问所需索引的数组中的任何索引来访问该值

const [a, b] = [1, 2, 3, 4, 5, 6];
console.log(a, b); // 1, 2
const [a, b,,, c] = [1, 2, 3, 4, 5, 6];
console.log(a, b, c); // 1, 2, 5

15. 使用与Rest运算符的Destructuring Assignment重新分配数组元素

const [a, b, ...arr] = [1, 2, 3, 4, 5, 7];
console.log(a, b); // 1, 2
console.log(arr); // [3, 4, 5, 7]

以达到对数组切片的目的.

16. 使用解构分配将对象作为函数的参数传递

const stats = {
  max: 56.78,
  standard_deviation: 4.34,
  median: 34.54,
  mode: 23.87,
  min: -0.75,
  average: 35.85
};
const half = (function() {
  "use strict"; // do not change this line

  // change code below this line
  return function half({max, min}) {
    // use function argument destructuring
    return (max + min) / 2.0;
  };
  // change code above this line

})();
console.log(stats); // should be object
console.log(half(stats)); // should be 28.015

17. 使用模板文字创建字符串

ES6的一个新功能是模板文字。
这是一种特殊类型的字符串,可以更轻松地创建复杂字符串。
模板文字允许您创建多行字符串并使用字符串插值功能来创建字符串。

const person = {
  name: "Zodiac Hasbro",
  age: 56
};

// Template literal with multi-line and string interpolation
const greeting = `Hello, my name is ${person.name}!
I am ${person.age} years old.`;

console.log(greeting); // prints
// Hello, my name is Zodiac Hasbro!
// I am 56 years old.

在上面的代码中需要注意到以下几点:
首先,该示例使用反引号(`)而不是引号('或“)来包装字符串。
其次,请注意字符串在代码和输出中都是多行的。
这样可以节省在字符串中的插入。

上面使用的$ {variable} 语法是占位符。

基本上,您不必再使用+运算符连接。
要将变量添加到字符串,只需将变量放在模板字符串中并用$ {和}换行。
同样,您可以在字符串文字中包含其他表达式,

例如$ {a + b}。

这种创建字符串的新方法使您可以更灵活地创建健壮的字符串。

const result = {
  success: ["max-length", "no-amd", "prefer-arrow-functions"],
  failure: ["no-var", "var-on-top", "linebreak"],
  skipped: ["id-blacklist", "no-dup-keys"]
};
function makeList(arr) {
  "use strict";

  // change code below this line
  const resultDisplayArray = 
  [ 
    `<li class="text-warning">${arr[0]}</li>`,
    `<li class="text-warning">${arr[1]}</li>`, 
    `<li class="text-warning">${arr[2]}</li>` 
    ];
  // change code above this line

  return resultDisplayArray;
}
/**
 * makeList(result.failure) should return:
 * [ `<li class="text-warning">no-var</li>`,
 *   `<li class="text-warning">var-on-top</li>`, 
 *   `<li class="text-warning">linebreak</li>` ]
 **/
const resultDisplayArray = makeList(result.failure);

18. 使用简单字段编写简明对象文字声明

ES6为轻松定义对象字符提供了很好的支持。

const getMousePosition = (x, y) => ({
  x: x,
  y: y
});

或者直接简写为:

const getMousePosition = (x, y) => ({ x, y });

其实这就是一个匿名函数,返回值为一个对象,用括号包裹起来了.

19. 用ES6编写简明的声明函数

在ES5中定义对象内的函数时,我们必须使用关键字函数,如下所示:

const person = {
  name: "Taylor",
  sayHello: function() {
    return `Hello! My name is ${this.name}.`;
  }
};

使用ES6,您可以在定义对象中的函数时完全删除函数关键字和冒号。
以下是此语法的示例:

const person = {
  name: "Taylor",
  sayHello() {
    return `Hello! My name is ${this.name}.`;
  }
};

20. 使用类语法定义构造函数

ES6使用关键字class提供了一种帮助创建对象的新语法。需要注意的是,类语法只是一种语法,而不是面向对象范例的完整的基于类的实现,与Java,Python,Ruby等语言不同。在ES5中,我们通常定义构造函数,并使用new关键字来实例化对象。

var SpaceShuttle = function(targetPlanet){
  this.targetPlanet = targetPlanet;
}
var zeus = new SpaceShuttle('Jupiter');

类语法只是替换构造函数创建:

class SpaceShuttle {
  constructor(targetPlanet){
    this.targetPlanet = targetPlanet;
  }
}
const zeus = new SpaceShuttle('Jupiter');

请注意,class关键字声明了一个新函数,并添加了一个构造函数,该函数将在调用new时调用 - 以创建新对象。

21. 使用getter和setter来控制对象的访问

class Book {
  constructor(author) {
    this._author = author;
  }
  // getter
  get writer(){
    return this._author;
  }
  // setter
  set writer(updatedAuthor){
    this._author = updatedAuthor;
  }
}
const lol = new Book('anonymous');
console.log(lol.writer);  // anonymous
lol.writer = 'wut';
console.log(lol.writer);  // wut

不解释

22. 理解import和require之间的差异

过去,函数require()将用于导入外部文件和模块中的函数和代码。虽然方便,但这会带来一个问题:某些文件和模块相当大,您可能只需要来自这些外部资源的某些代码。ES6为我们提供了一个非常方便的工具,称为import。有了它,我们可以选择加载到给定文件中的模块或文件的哪些部分,从而节省时间和内存。请考虑以下示例。想象一下math_array_functions有大约20个函数,但我在当前文件中只需要一个countItems。旧的require()方法会迫使我引入所有20个函数。使用这种新的导入语法,我可以引入所需的功能,如下所示:

import { countItems } from "math_array_functions"

23. 使用export重用代码块

当我们想要一些代码 - 一个函数或一个变量 - 可以在另一个文件中使用时,我们必须将其导出才能将其导入另一个文件

const capitalizeString = (string) => {
  return string.charAt(0).toUpperCase() + string.slice(1);
}
export { capitalizeString } //How to export functions.
export const foo = "bar"; //How to export variables.

24. 使用*从文件导入所有内容

import * as myMathModule from "math_functions";
myMathModule.add(2,3);
myMathModule.subtract(5,3);

25. 使用导出默认值创建导出回调

你需要知道另一种导出语法,称为导出默认值。
通常,如果只从文件导出一个值,你将使用此语法。
它还用于为文件或模块创建返回值。

export default function add(x,y) {
  return x + y;
}

注意:由于export default用于声明模块或文件的返回每个模块或文件中只能有一个值作为默认导出。
此外,不能将export default用于var,let或const

上一篇下一篇

猜你喜欢

热点阅读