摧枯拉朽,说说ES6的三把火
我是 Jser 我骄傲
JavaScript 如今可谓是屌丝逆袭高富帅的代名词哈,从当初闹着玩似的诞生到现在 Github 上力压群雄的人气王,JS 搭着互联网的顺风车一路高歌,本身也从一个爷爷不疼奶奶不爱的杀马特小脚本蜕变为一门高大上的主流编程语言。运气固然重要,ES6 也让大家看到了这门语言自身的努力和上进,相信 JavaScript 定大有可为。
ES6 发布于 2015 年 6 月,因此也叫 ES2015,距今已有两年多。2015 年是铭心刻骨的一年,这一年,股市崩盘,千古跌停,手里的两个票更是挨了腰斩,宝宝心里苦。同是这一年,ES6 标准落地,作为一名前端开发,宝宝心里又乐开了花。
ES6 的新语法很多很碎,如果想系统地学习一遍,强烈推荐阮一峰老师的 ECMAScript 6 入门。本文的目的不是要介绍 ES6 的新语法,而是想谈谈 ES6 为JavaScript 这门语言本身带来了什么,同时这也是在咱看来 ES6 最重要最激动人心的特性。
作用域
作用域一直是程序设计语言的基础设施。JavaScript 也有作用域,但它的作用域有点怪,稍不留神就会掉到坑里。
JavaScript 的作用域(scope)有三种类型,分别是 Local,Closure 和 Global,对应的三种变量类型分别是局部变量,闭包变量和全局变量。
比如下面一段代码:
var a = 'global'
function outer(){
var b = 'closure'
return function inner(){
var c = 'local'
console.log(a + ':' + b + ':' + c)
}
}
outer()()
在 Chrome 控制台执行上面代码,当执行 outer()() 时,a 和 outer 都是全局变量,浏览器环境中的全局变量全部挂在全局 window 对象上。b 是闭包变量, 对 outer 函数内定义的函数内部保持可见。c 则是局部变量,只对 inner 函数内部可见。
目前为止看上去似乎没什么问题,接下来看点有问题的:
if(true){
var _a = 1
}
console.log(_a)
正常情况下变量 _a 的值应该是 undefined 才对,然而不要以为你以为就是你以为的。在 JS 中 if 语句块里定义的变量 _a 直接变成了全局变量,也就是通过 window._a 可访问。如果是从C语言,Java等主流编程语言转过来的开发者就会更加迷惑了,这简直就是TMD不科学。
在 JS 中,诸如 for,while,switch 等可接大括号的代码块都是不能定义局部变量的,在其中定义的变量通通会是全局变量,也就是说大家已经习以为常的块作用域在 JavaScript 中是不存在的,能够定义局部变量的只有函数这个第一公民。这不科学,不合理,不符合社会主义核心价值观\抓狂。
一声霹雳,ES6 落地,完美地弥补掉了上面 JavaScript 暴露的作用域缺陷。这就意味着从此以后你可以以为你以为的就是你以为的了。ES6 为了向后兼容,var 还是原来的 var 保持不变,在此基础上又新添了一个声明变量的关键字 let 和一个声明常量的关键字 const。
{
let a = 1
}
console.log(a)
// Uncaught ReferenceError: a is not defined
完善的作用域机制可有效地避免命名污染,提高程序的可靠性,减少隐晦的bug,尤其是在开发大型多人协作项目时作用尤为明显。
鉴于以上所分析的各种利弊,请自始至终地使用 let,而不要再让 var 这个混小子出现在视线里。用 var 危险,后果自负。
模块系统
模块化,模块化,模块化,重要的事情说三遍,这是工程化的第一要务,是控制软件复杂度的最重要措施,没有之一。然而 2015 年之前的 JavaScript 语言是没有模块系统的。C语言有 include,Java 有 import,连 CSS 都有个蹩脚的 @import,wrnmmp,JavaScript 却只有 undefined。有条件要上,没条件创造条件也要上。于是乎,JavaScript 社区里的各位勇士造出了各种各样实现模块化的轮子,AMD,CMD,UMD 全蹦出来了。不想用又苦于没有好的解决方案,只能在内心呐喊,这不科学,不合理,不符合···\抓狂。
霹雳哗啦,ES6 落地,带来了原生的模块系统,优雅又简单,丝滑般的体验冲淡了腰斩给咱带来的痛,脸上又洋溢出了久违的笑容。
最基本的使用:
/* add.js */
export function add(a, b){
return a + b
}
上面定义并导出了一个 ES 模块。接下来就可以在任一个逻辑文件里引用:
/* main.js */
import {add} from './add'
add(1, 3)
模块系统哪家强,ES6 最猖狂。ES6 一出,快刀斩乱麻,直接终结了前端长期的模块化乱象,实现了大一统。唯一的遗憾是 Node.js 对 ES6 模块系统的支持还不是无缝过渡。不过这个还好,毕竟 Node.js 的 CommonJS 用起来还是相当顺手的。
有了语言层面的模块系统,JavaScript 也在语言性质上完成了蜕变,不再是一个打遍互联网酱油的小脚本,而成长为一门举重若轻的主流编程语言。
模块系统是大型项目不可或缺的标准配置,对项目的开发和维护都非常重要。所以把它列为 ES6 所带来的最重要特性丝毫不为过。
类(Class)
其实这个特性相比前两个倒是没那么重要,说白了,类(Class)做的就是 JS 原型(prototype)做的那点事——继承,咱觉得这是一个没它也行,有它更好的语法糖功能。之所以把它列在这是因为咱看 prototype 不爽很久了。
JS 基于原型的继承机制借鉴自 Self 语言。正如 JS 的设计者所言“它是 C 语言和 Self 语言一叶情的产物”。原型继承是很不直观的,或者可以说是非主流的。面向对象程序设计中典型的继承是基于类的继承,例如 Java,C++ 等主流编程语言实现的均是基于类的继承。
使用 prototype 会出现 jQuery 的 jQuery.prototype.init.prototype = jQuery.prototype 这种让人瞬间石化的代码。况且咱左看右看,上看下看也没看出来原型继承相较于类式继承有啥优点可言,反而是越看越拙。咱第一眼看到 prototype 这货就很不顺眼,也许是因为从 C++ 开发过来的缘故吧。
好在 ES6 带来了 class,刚发现这个特性的时候咱乐的一宿没睡着觉,有一种久别重逢,相见恨晚的赶脚。
来看个最简单示例:
/* Shape.js */
export class Shape{
this.x = 0
this.y = 0
}
英雄联盟里的盲僧说过“如果类不是为了继承,那将毫无意义”。
/* main.js */
import {Point} from "./Point"
class Triangle extends Point{
constructor(){
super()
this.sides = 3
}
}
let a = new Triangle()
这代码看着多直观,多大方,多舒坦。面向对象的概念已经在前端被越来越广泛的传播开来,咱是非常推崇 class 的继承方式的,不知道大家喜欢用哪个,反正在咱的代码里已经是看不到 prototype 的影子了。
以上就是咱认为 ES6 带来的三把火。肯定有人要质疑了“怎么没有 Promise 啊”,需要申明一下,Promise 在 node 偏后端开发中比较实用,在前端的日常开发中并不常用,而本文是从偏前端的角度来说的,这是咱这两年开发中受益最大的三个特性。
摧枯拉朽,说说ES6的三把火的更多相关文章
- React与ES6(三)ES6类和方法绑定
React与ES6系列: React与ES6(一)开篇介绍 React和ES6(二)ES6的类和ES7的property initializer React与ES6(三)ES6类和方法绑定 React ...
- 关于阮一峰老师es6(第三版)中管道机制代码的理解浅析
最近正在学习阮一峰老师的es6(第三版)教材,在学到第七章<函数的扩展>中的箭头函数嵌套时,文中提到了一个关于“管道机制”的示例,文中源代码如下: //es6(第三版)教材中的管道机制源代 ...
- 深入浅出ES6(三):生成器 Generators
作者 Jason Orendorff github主页 https://github.com/jorendorff ES6生成器(Generators)简介 什么是生成器? 我们从一个示例开始: ...
- JavaScript学习笔记 -- ES6学习(三) 变量的解构赋值
1.解构赋值的定义 在ES6中,允许按照一定模式,从数组和对象中提取值(所谓解构),然后对变量进行赋值. var a = 1; var b = 2; var c = 3; //等价于 var [a, ...
- ES6核心内容精讲--快速实践ES6(三)
Promise 是什么 Promise是异步编程的一种解决方案.Promise对象表示了异步操作的最终状态(完成或失败)和返回的结果. 其实我们在jQuery的ajax中已经见识了部分Promise的 ...
- 用vue.js学习es6(三):数组、对象和函数的解构
一.数组的解构: 以前的方式: var arr = [1,2,3]; console.log(arr[0]); //1 console.log(arr[1]); //2 现在的方式: var [a,b ...
- es6(三):es6中函数的扩展(参数默认值、rest参数、箭头函数)
1.函数可以设置参数默认值 function test1(x,y=1){ console.log(x,y) } test1(10)//10 1 2.rest参数:形式为...变量名 function ...
- 从零开始学 Web 之 ES6(三)ES6基础语法一
大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:ht ...
- ES6基础三(对象)
对象赋值 在es6中,可以直接将声明的变量赋值给对象: Object.keys().Object.values()和Object.entries() 在ES6中,允许我们使用变量作为对象的ke ...
随机推荐
- openstack学习心得:keystone 架构、概念、访问流程
1.keystone 介绍及其组成 OpenStack Identity 服务提供了一个单一的功能集合,包括管理认证,授权和服务目录. Identity 服务通常作为和用户第一个交互的服务.一旦认证成 ...
- Windows Forms DataGridView中合并单元格
Windows Forms DataGridView 没有提供合并单元格的功能,要实现合并单元格的功能就要在CellPainting事件中使用Graphics.DrawLine和 Graphics.D ...
- SSM 五:Spring核心概念
第五章:Spring核心概念 一.Spring Ioc 优点: 1.低侵入式设计 2.独立于各种应用服务器 3.依赖注入特性将组建关系透明化,降低耦合度 4.面向切面编程的特性允许将通用性任务集中式处 ...
- ios -Unity3D的EasyAR集成到已经有项目中。
近期 在做AR这一块,用EasyAR集成到iOS端,由于现在到项目已经上线,下一版本要做一个AR功能,于是迫于需求需要,自己研究和翻阅读好多集成到资料. 通过整理分出几个重要到模块,其中在这里指出Xc ...
- Mac_Homebrew
Homebrew作为OS X上强大的包管理器,为系统软件提供了非常方便的安装方式,独特式的解决了包的依赖问题,并不再需要烦人的sudo,一键式编译,无参数困扰,真的,你值得拥有. brew 的安装: ...
- pandas选择数据-【老鱼学pandas】
选择列 根据列名来选择某列的数据 import pandas as pd import numpy as np dates = pd.date_range("2017-01-08" ...
- iOS设置圆角的方法及指定圆角的位置
在iOS开发中,我们经常会遇到设置圆角的问题, 以下是几种设置圆角的方法: 第一种方法: 通过设置layer的属性 代码: UIImageView *imageView = [[UIImageView ...
- Spring4 JDBC详解
Spring4 JDBC详解 在之前的Spring4 IOC详解 的文章中,并没有介绍使用外部属性的知识点.现在利用配置c3p0连接池的契机来一起学习.本章内容主要有两个部分:配置c3p0(重点)和 ...
- javascript面向对象编程(OOP)——汇总
目录 一.JS的解析与执行过程 预处理阶段 执行阶段 二.作用域 块作用域 函数作用域 动态作用域 词法作用域 三.闭包 什么是闭包 闭包的好处 四.类与对象 对象 类 原型(prototype) t ...
- Python案例分享
1.过桥(爬金字塔): 1 i = 1 2 while i <= 9: 3 if i < 6: 4 j = 0 5 while j < i: 6 print('*',end=' ') ...