有关作用域有更深入的内容,本篇探讨的是最容易理解的部分。理解作用域可以更好的组织代码结构,减少各个上下文的污染。在 ES6 中引入了块及作用域的概念,这是在之前都没有的,可以查阅 ES6 中对应的内容进行了解。
数组的解构赋值是,通过新建一个数组,数组内的变量和目标数组是一一对应的,按照索引的方式去获取值,然后赋值给指定索引上的变量。在 ES6 之前,想获取数组中的值,需要通过 Array[index] 的方式来获取值,这种方式的好处在于可以获取数组上指定索引的值,如果我们想把数组的每一项的值都取出来,赋给变量,这样的写法就显得很笨拙:var arr = [10, 20];console.log(arr[0]); // 10console.log(arr[1]); // 20上面的取值方式是 ES6 之前的写法,有了 ES6 的解构赋值就简单了很多,下面看 ES6 解构赋值是怎么取数组的对应值的:var [a, b] = [10, 20];console.log(a); // 10console.log(b); // 20上面的例子中先声明一个数组,分别在数组的 0 和 1 的索引位置上放置变量 a 和 b,对应着需要获取数组的索引位置,这样就可以从数组当中取到我们想要的值了。
ES6 对字符串进行了扩展,使之更具有表达力,在 ES5 中字符串的功能是很单一,只能定义变量,不能在字符串中进行逻辑运算,只能使用 + 通过拼接的方式实现。另外,字符串的拼接和换行都需要借助 + 和 \n 才能实现,很麻烦更容易出错。这无疑限制了我们对字符串的操作。ES6 对 ES5 中存在的问题进行了修复和扩充,本节我们来学习 ES6 中的模版字符串语法,在本节你可以了解一下内容:字符串换行;字符串拼接;字符串中包含逻辑运算;带标签的模版字符串。下面我们先来看看在 ES5 中字符串都是哪些使用场景,从而更好地对比 ES6 所提供的模版字符串到底有什么好处,解决了那些问题。
当函数体内有返回值时,ES6 的箭头函数可以省略大括号:var sum = (num1, num2) => num1 + num2;当传递的参数只有一个时,圆括号也可以省略:var sum = num => num + 10;下面看个使用 map 求和的例子:// ES5[1,2,3].map(function (x) { return x * x;});// 等同于ES6[1,2,3].map(x => x * x);对比 ES5 可以看出箭头函数的简洁表达,更加准确明了。
在 ES6 之前如果我们想交换两个变量的值时,我们需要借助一个中间的值来过渡,下面是要交换 a、b 值的过程:var a = 1;var b = 4;var m = a;a = b;b = m // a=4, b=1在交换 a、b 值时,需要借助中间的变量来中转,使用 ES6 解构赋值就很简单:var a = 1;var b = 4;[a, b] = [b, a] // a=4, b=1
自 ES6 起,终于迎来了 class,对于开发者来说,终于可以使用基于类的面向对象式编程。TypeScript 在原 ES6 中类的基础上,还添加了一些新的功能,比如几种访问修饰符,这是在其他面向对象语言中早就实现了的。JavaScript 的类作为语法糖,我们不但需要知道怎么去使用,还应该了解其本质,涉及到原型的部分希望大家能深入理解。
本节主要学习了 ES6 新增的数据结构 Set 和 Map 的基本使用,并介绍了 Set 和 Map 与 Array 和 Object 之间的转化方法。从上面的学习中我们知道,ES6 新增 Set 和 Map 这两个数据结构,在弥补 JavaScript 数据结构的同时并规范了操作数据的方法。让 JavaScript 更加像一门成熟的语言前进。接下来的几个小节我们会对 Set 和 Map 进行详细的介绍。
ES6 还提供了其他的字符串操作的方法,接下来的几节专门讲解字符串中新增的方法,更好地解决实际的开发问题。另外,ES6 还增加了模版字符串和带标签的模板字符串,在 模板字符串中进行了讲解,遗忘的可以去看看。本节主要讲解了,字符串对 Unicode 的增强,还有对字符串增加了遍历接口,非常实用。
在定义函数时,往往需要给参数添加默认值,ES6 中可以直接在圆括号中进行赋值。var sum = (num1, num2 = 2) => num1 + num2;console.log(sum(1)) // 3在使用 function 关键字定义函数时,如果要给传递的参数设置默认参数,只能在函数体内进行赋值操作,ES6 简化了默认参数的赋值过程。
ES6 的模块化设计思想是尽量静态化,使得编译时就能确定模块的依赖关系,只能在顶级作用域。模块系统中,每个文件都是一个模块,模块之间都是相互独立。在 ES6 模块中自动采用 严格模式 ,不知道的同学可以去看看,对于学习 JavaScript 语言有一定的帮助。
在 ES6 中,提供了两个常量 Number.MAX_SAFE_INTEGER 与 Number.MIN_SAFE_INTEGER ,可以获得到在 JavaScript 可以表示的最大值与最小值(安全数)。安全整数范围为 -(253 - 1)到 253 - 1 之间的整数,包含 -(253 - 1)和 253 - 1 。console.log(Number.MAX_SAFE_INTEGER); // 输出:9007199254740991console.log(Number.MIN_SAFE_INTEGER); // 输出:-9007199254740991在 ES6 中没必要自己去做比较,可以使用 Number.isSafeInteger() 方法判断传入的数字是不是一个安全数。Number.isSafeInteger(11111111111111111111); // falseNumber.isSafeInteger(996); // true
ES6 允许直接写入变量和函数,作为对象的属性和方法
本节我们一起学习下 ES6 中的 let,在 ES5 中变量的方法只有一个 var ,但是使用 var 来定义的变量存在很多缺陷和弊端,ES6 引入了 let 语句来声明变量,同时引入了很多概念,比如块级作用域、暂存死区等等。限制了任意声明变量,提升了程序的健壮性。
本节主要学习了 ES6 中 class 类的使用和相关的知识点,需要明确的是 class 类就是一个语法糖,底层还是基于现有的原型对象的继承来实现的。所以要想深入理解 ES6 的 class 就需要对 ES5 中的构造函数有深入的理解,另外,我们可以使用 babel 进行转译,得到的代码就是使用构造函数来实现的。
现在的高级浏览器还能完全地支持 ES6 的模块化,如何在浏览器中运行 ES6 模块呢?有两种方式:在浏览器中直接运行 ES6 的模块化,但是需要做一定的工作,不能像之前直接在本地浏览器中打开一个 html 中引入 JS 文件;使用 Webpack、rollup 等模块化打包工具,html 引入编译后的 js 文件。这两种方式各有优缺点,第一种是原生的使用方式,浏览器兼容要求比较高,第二种使用的是第三方打包编译工具可以很好地解决浏览器兼容问题,但是会有一定的学习成本,并且不能直接在浏览器中运行,只能使用编译后的文件。
本章讲解了 ES6 的 Array.of() 方法,该方法用于创建数组,主要为了替换 Array() 方法,弥补 Array() 方法的不足。
Lodash 是非常常用的工具库,也提供了许多 ES6 提供的同名的方法,可以充当 polyfill 使用。
我们知道迭代对象可以使用 for...in 循环来做,但 for...in 循环会枚举其原型链上的属性,这使得我们在遍历时需要判断是不是原型链属性。Object.keys() 可以接受一个对象返回一个可枚举的数组,数组中的元素的排列顺序和使用 for...in 循环遍历返回的顺序是一致的。Object.keys() 在 ES5 中就有此方法,但是在设计上存在一定的缺陷,ES6 对其底层做了重大的更新。比如:在 ES5 中,如果此方法的参数不是对象(而是一个原始值),那么它会抛出 TypeError。在 ES2015 中,非对象的参数将被强制转换为一个对象。// ES5 代码Object.keys("imooc"); // TypeError: "imooc" is not an object// ES6 代码Object.keys("imooc"); // ["0", "1", "2", "3", "4"]现在的浏览器已经基本都支持 ES6 的结果了,下面我们来系统性地认识一下 Object.keys()。
在 ES5 中,如 parseFloat、parseInt 等都是全局方法,在 ES6 中把处理数值的一些方法都移植到了 Number 对象上了。parseInt('123'); // 123Number.parseInt('123'); // 123上面的代码可以看到,Number 对象下也有 parseInt 的方法,并且所有的数值方法在 Number 上也是一一对应的,功能基本相同,有些方法还做了扩展。在后面的小节中我们会对 Number 上的方法和全局的方法进行对比,看它们有什么不同,ES6 又解决了什么问题。
ES6 对 Number 的属性进行了丰富,能够适用更多的场景。
为了保持方法上的统一,把全局下的 parseInt() 和 parseFloat() 移植到 ES6 的 Number 对象上。ES6 的 Number 对象上提供的 Number.isFinite () 和 Number.isNaN () 两个函数是相同的,如何证明 Number 下的这两个方法只是移植全局的呢?可以利用 === 运算符来判断,如下实例:Number.parseInt === parseInt; // trueNumber.parseFloat === parseFloat; // true上面的代码返回的结果都为 ture 说明此两种函数和全局是一样的,没有发生变化。具体的使用方法可以参考 ES5 中的 parseInt() 和 parseFloat() 函数。// ES5的写法parseInt('12.34') // 12parseFloat('123.45#') // 123.45// ES6的写法Number.parseInt('12.34') // 12Number.parseFloat('123.45#') // 123.45将这两个全局方法移植到 Number 对象上,为了逐步减少全局性方法,使语言逐步模块化。
Number.isInteger() 是 ES6 新增的函数,用来判断给定的参数是否为整数。Number.isInteger(25) // trueNumber.isInteger(25.1) // false如果被检测的值是整数,则返回 true,否则返回 false。注意 NaN 和正负 Infinity 不是整数。Number.isInteger(0); // trueNumber.isInteger(1); // trueNumber.isInteger(-100000); // trueNumber.isInteger(0.8); // falseNumber.isInteger(Math.PI); // falseNumber.isInteger(Infinity); // falseNumber.isInteger(-Infinity); // falseNumber.isInteger("100"); // falseNumber.isInteger(true); // falseNumber.isInteger(false); // falseNumber.isInteger([1]); // false上面的代码基本涵盖了 JavaScript 中的值的判断,在一些不支持 ES6 语法的浏览器中可以使用上面的两种方式进行 Polyfill 处理。
在 Chrome浏览器 下通过访问对象的 __proto__ 属性可以取到对象的原型对象,这是所有对象都具备的属性。var date = new Date();console.log(date.__proto__);__proto__ 具有兼容性问题,因此开发中尽量不要使用到,他不在 ES6 之前的标准中,但是许多旧版浏览器也对他进行了实现。在 ES6 中 __proto__ 属性 被定制成了规范。
箭头函数的使用很简单,使用 => 来定义函数,下面对比 ES5 和 ES6 定义函数的对比。// ES5var sum = function () { // todo};// ES6var sum = () => { // todo}
先创建一个带有 ES6 语法的 JS 文件:// index.jsconst fn = (a, b) => a + b;const added = fn(1, 2);然后修改一下 package.json 的 scripts 选项。// package.json"scripts": { "compile": "babel index.js"}保存后就可以进入终端,输入命令 npm run compile,npm 就会去执行 compile 对应的命令,也就是使用 Babel,对 index.js 文件进行编译。但执行后会发现代码并没有变成非 ES6 的代码,那是因为没有告诉 Babel 想要将现有代码编译成什么样的代码,这时候就需要提供一个配置文件。