1.声明变量的关键字:const 和 let
JavaScript ES6中引入了另外两个声明变量的关键字:const和let。在ES6中,我们将很少能看到var了。
const关键字
const声明一个只读的常量。一旦声明,常量的值不能被改变。
const声明一个变量,就必须立即初始化,不能留到以后再赋值。
需注意:若这个变量是数组或者对象的话,它里面持有的内容是可以被更新的。
因为使用const声明一个复合类型的数据(主要是对象和数组),变量名不指向数据,而是指向数据的地址。
举例如下:
//这种写法是不可行的
const str = 'hello world';
str = 'hello kitty'; //TypeError: Assignment to constant variable
//这种写法是可行的
const arr = [1,2,3];
arr[0]=9;
let关键字
被let关键字声明的变量可以被改变。
举例如下:
//这种写法是可行的
let str = 'hello world';
str = 'hello kitty';
需注意:
- let声明的变量只有所在的代码块有效。
- 不存在变量的提升:使用let声明的变量要在声明后使用,否则会报错。
//使用var定义的变量,存在变量的提升。
console.log(a); //undefined
var a = 10;
//使用let定义的变量,不存在变量的提升,所以下面的代码会报错
console.log(b); // ReferenceError: b is not defined
let b = 20;
- 暂时性死区:使用let命令声明变量之前,该变量都是不可用的。
- typeof不再是一个百分百安全的操作
typeof c; // ReferenceError: c is not defined
let c;
ES6声明变量的六种方法
ES5只有两种声明变量的方法:var
和function
ES6除了添加let
和const
,还有另外两种声明变量的方法:import
命令和class
命令。所以,ES6一共有6种声明变量的方法。
2.顶层对象的属性
顶层对象,浏览器中指的是window对象,在Node中指的是global对象。
ES5中,顶层对象的属性和全局变量是等价的。举例:
window.a = 1;
a //1
a = 2;
window.a //2
ES6为了改变这一点,一方面规定,为了保持兼容性,var
和function
命令声明的全局变量,依旧是顶层对象的属性;
另一方面规定,let
命令,const
命令,class
命令声明的全局变量,不属于顶层对象的属性。
也即是说,从ES6开始,全局变量将逐步与顶层对象的属性脱钩。
举例如下:
var a = 1;
window.a //1
let b=2;
window.b //undefined
上述代码中,全局变量a
由var
命令声明,所以是顶层对象的属性;全局变量b
由let
命令声明,所以它不是顶层对象的属性,返回undefined
3.模板字符串
传统的JavaScript语言,输出模板通常是用字符串拼接起来的,这种写法相当繁琐不方便,于是ES6引入了模板字符串来解决这个问题。
模板字符串(template string)是增强版的字符串,用反引号(`)标识。可以当做普通的字符串使用。也可以用来定义多行字符串,或者在字符串中嵌入变量。
举例如下:
//普通字符串
`In JavaScript '\n' is a line feed`
//多行字符串
`In JavaScript this is
not legal`
//字符串中嵌入变量
let name = 'Bob',time = 'today';
`Hello ${name},how are you ${time}`
上述代码中的模板字符串,都是用反引号表示的。
需注意:如果再模板字符串中需要引入反引号,则前面要用反斜杠转义。
举例如下:
let greeting = `\Yo\` world
模板字符串中嵌入变量,需要将变量名写在
${ } 之中。模板字符串中还能调用函数
function fn(){
return "Hello World";
}
`foo ${fn()} bar`
//foo Hello World bar;
4.箭头函数
ES6中允许使用“箭头”(=>)定义函数。
举例如下:
var f = v => v;
//上面的箭头函数等同于
var f = function(v){
return v;
}
若箭头函数需要多个参数,则参数要用圆括号括起来。
var f = () => 5;
//等同于
var f = function(){return 5;}
var sum = (num1,num2) => num1+num2;
//等同于
var sum = function(num1,num2){
return num1 + num2;
}
由于大括号被解释为代码块,所以,如果箭头函数直接返回一个对象,必须在对象外面加上括号,否则会报错。
//报错
let getTempItem = id => {id:id,name:"temp"};
//不报错
let getTempItem = id => ({id:id,name:"temp"});
箭头函数与变量结构可以结合使用
const full = ({first,last}) => first + '' + last;
//等同于
function full(person){
return person.first + '' + person.last;
}
5.使用export和import实现模块化
由于JavaScript是没有模块这一系统的,前辈们为了解决这一问题,提出来很多规范,其中最长用的就是 CommonJs 和 AMD 两种。前者用于服务器,后者用于浏览器。
简单看一下CommonJs的模块化方法
在CommonJs中,暴露模块使用
module.exports
,加载模块有一个全局的方法:
require()
,用于加载模块。
示例代码:
//app.js
let person = {
age:'20',
name:'Jolin'
};
module.exports = person; //所暴露出的对象
//index.js
let person = require('./app'); //加载app模块
console.log('姓名'+person.name); //姓名Jolin
注意:CommonJs 的模块化方法是运行于服务器端的,直接在浏览器端运行是不识别的,所以进入安装 nodejs 的目录,打开 cmd 命令窗口,键入命令node index.js
来运行吧~
好了,言归正传~ ES6提供了简单的模块系统,可以取代 CommonJs 和 AMD 规范。那就是export
和 import
。
ES6中新增了两个命令
export
和
import
,
export
命令用于暴露出模块对外的接口,而
import
则用于输入某一模块。
示例代码:
//export.js
exports var firstName = 'Micheal';
exports var lastName = 'JackJson';
exports var year = 1958;
//import.js
import {firstName,lastName} from './export.js'
console.log(firstName+' '+lastName); //Micheal JackJson
由于浏览器目前对ES2015(ES6)的语法支持不是很强,所以,即便是Firefox和Chrome浏览器,若版本较低,可能还是只支持一部分语法,那么如何才能让ES6语法能够正常的在各个浏览器运行呢?则就需要将编写的JS文件通过一些编译工具编译成ES5的语法,那么babel工具就可以实现这个转义。
然而,babel 只能转新的JavaScript句法(syntax)而不能转新的API,而且像import
和export
两个命令在现在任何浏览器都是不支持的,同时babel也无法转换其为浏览器支持的ES5,因为:
babel只是个翻译,假设a.js 里 import 了 b.js, 对a.js进行转码,只是翻译了a.js,并不会把b.js的内容给读取合并进来, 如果想在最终的某一个js里,包含 a.js,b.js 的代码,那就需要用到打包工具。
所以,我们可以使用webpack工具将带有import
和export
语法的JS文件,通过打包工具生成所有浏览器都支持的单个JS文件。