4.es6的几个新特性
糖语法 首先,语法糖是一种语法,使得语言更容易理解和更具有可读性,它使语言相对我们来说变得更"甜"。这也意味着ES6的一些"新"的特点并不是真的新,只是试图简化语法而已,让我们编程更容易。这样就无需使用老式的取巧的方法编写你的代码,而是可以一种更简单的方式来编写代码,那就是使用糖语法。 javascript并不像其他面向对象语言一样支持类这个概念,相反js使用function和prototype模拟类的概念。 下面是创建类的新语法,如果你有来自Java或其他OO语言的背景你会很熟悉: class Project { constructor(name) { this.name = name; } start() { return "Project " + this.name + " starting"; } } var project = new Project("Journal"); project.start(); // "Project Journal starting" 你在这个类中定义的所有方法都被加入这个类的原型prototype中。 既然JS不支持类,那么它支持继承吗? 是的,JS中继承是通过prototype实现。下面是WebProject子类继承Project类的代码: class WebProject extends Project { constructor(name, technologies) { super(name); this.technologies = technologies; } info() { return this.name + " uses " + arrayToString(this.technology); } } function arrayToString(param) { // ... some implementation } var webJournal = new WebProject("FrontEnd Journal", "javascript"); webJournal.start(); // "FrontEnd Journal starting" webJournal.info(); // "FrontEnd Journal uses javascript" 注意到在WebProject 构造器中,调用了Project的构造器,这样可以使用它的属性和方法。 模块Module 如果你想将所有js放在一个文件中,或者你要在应用的不同地方使用相同的功能,你就要使用模块,记住魔术的关键词是export,在你的函数之前使用export。 假设Project 和 WebProject 都储存在application.js文件中,如下源码结构: myproject (folder) | -- modules (folder) | | | -- helpers.js | -- application.js 如果我们从application.js中分离arrayToString(),然后放入modules/helpers.js,这样我们在其他地方可以重用它: // modules/helper.js export function arrayToString(param) { // some implementation } 这样我们只需要导入我们的模块即可: // application.js import { arrayToString } from 'modules/helpers'; class WebProject extends Project { constructor(name, technologies) { super(name); this.technologies = technology; } info() { return this.name + " uses " + arrayToString(this.technology); } } // ... let和const ES6中有两个新特性:let和 const,为了理解let,我们需要记住var是创建函数生存期内的变量: function printName() { if(true) { var name = "Rafael"; } console.log(name); // Rafael } 不像Java或其他语言,任何变量在JS中是在一个函数内创建,它会升级到哦函数之外部,不管你在哪里定义变量,都和你在函数顶部定义一样,这个行为称为hoisting。 上面代码用下面方式容易理解些: function printName() { var name; // variable declaration is hoisted to the top if(true) { name = "Rafael"; } console.log(name); // Rafael } 那么let是如何工作呢,和hoisting有什么关系,我们导入let的代码如下: function printName() { if(true) { let name = "Rafael"; } console.log(name); // ReferenceError: name is not defined } let是在一个代码块内,变量名只能在代码块中可见。 function printName() { var name = "Hey"; if(true) { let name = "Rafael"; console.log(name); // Rafael } console.log(name); // Hey } 总结:var是function-scoped,而let是 block-scoped. const是创建常量使用,一旦创建就一直不会被概念,如下: const SERVER_URL = "http://www.jdon.com" ES6还有其他新功能:Map, WeakMap, generators 和Proxies 那么什么时候可以使用ES6这些特性呢?可见下面这个网址: http://kangax.github.com/es5-compat-table/es6/ Node.JS的ES6特性可见:ES6 for Node 1. Function参数默认值 曾几何时,你编写了很多次如下代码: function beginTeleportation (who, options) { options = options || {} } 现在检查函数参数是否存在再也没有必要了, Default function parameters 默认函数参数能够让定义函数的默认参数。 function sayCosmicGreeting (greeting = 'Greetings', name = 'Earthling') { console.log(`${greeting}, ${name}`) } sayCosmicGreeting() // Greetings, Earthling sayCosmicGreeting('Salutations', 'Martian') // Salutations, Martian 这里函数参数greeting和name都有自己默认值,所以,如果你没有赋值空参数调用,就会输出默认值Greetings和 Earthling。 2.Rest参数 传递许多参数到函数中需要使用arguments 关键词: function sayCosmicGreetingTo (greeting) { const beings = arguments.slice(1) beings.forEach(being => { console.log(`${greeting}, ${being}`) }) } sayCosmicGreetingTo('Hello', 'Earthling', 'Martian', 'Neptunian') 上述代码问题会报错:TypeError: arguments.slice is not a function,因为arguments 不是实际数组,只是类似,为了能正常工作,你需要使用数组原型的call函数: Array.prototype.slice.call(arguments, 1) 但是这些处理手法对于初学者很费解,而Rest parameters解决这个问题,给你一个真正实际的Array数组实例: function sayCosmicGreetingTo (greeting, ...beings) { beings.forEach(being => { console.log(`${greeting}, ${being}`) }) } sayCosmicGreetingTo('Hello', 'Earthling', 'Martian', 'Neptunian') 注意到函数参数beings之前有“...”前缀,这个前缀表示这是一个数组,从0到数组最大长度之间的元素值是由实际传入参数决定的。 3.解构 在Javascript中普遍模式是将一个对象作为配置可选项,以前,这些选项得手工从对象中分解出来然后分配给相应变量。 function beginDepartureSequence (options) { const captain = options.captain const ship = options.ship const destination = options.destination console.log(`Blast off sequence initiated for Captain ${captain} on ship ${ship} flying to ${destination}`) } beginDepartureSequence({ captain: 'Rey', ship: 'Millennium Falcon', destination: 'Jakku' }) 现在使用 destructure 可以直接将对象解构到变量,无论顺序: function beginDepartureSequence (options) { const { destination, captain, ship } = options console.log(`Blast off sequence initiated for Captain ${captain} on ship ${ship} flying to ${destination}`) } beginDepartureSequence({ captain: 'Rey', ship: 'Millennium Falcon', destination: 'Jakku' }) 上面options对象被直接解构分配给了变量destination, captain, ship三个,我们可以做得更好,可以直接在函数参数中声明这些变量名: function beginDepartureSequence ({ destination, ship, captain }) { console.log(`Blast off sequence initiated for Captain ${captain} on ship ${ship} flying to ${destination}`) } beginDepartureSequence({ captain: 'Rey', ship: 'Millennium Falcon', destination: 'Jakku' }) 以上只是简单几个新特点,更多支持Javascript6 或Javascript7的特性可以参考:http://node.green/