使用Babel编译ES6
1、下载安装babelnpm install babel-cli -g我们之所以可以使用babel命令,是因为在全局环境下会生成一些xxx.cmd的文件,而这里的xxx就是可以在doc窗口中执行的命令执行babel命令后,可以完成一些编译或者其他任务,原因是执行babel命令后,会自动加载处理任务的文件;配置.babelrc文件,安装在一些语言解析包我们需要把.babelrc文件配置在当前项目的根目录下注意:在电脑上不能直接创建没有文件名的文件,但是可以在webS中new->file来创建,或者使用命令创建m1、babelrc这个后缀名在某些ws中是不识别的,我们需要设置关联2、在这个文件中编写内容:
{
"presets":[],//存的是我们编译代码时候需要依赖的语言解析包
"plugins":[]//存的是我们编译代码时候需要依赖的插件信息
}
3、安装依赖的语言解析包在当前项目的根目录下安装npm install babel-preset-latest安装最新已经发布的语言标准解析模块npm install babel-preset-stage-2 安装当前还没有发布但是已经进入草案的语言解析模块4、完成最后.babelrc
{"presets":["latest","stage-2"],//存的是我们编译代码时候需要依赖的语言解析包"plugins":[]//存的是我们编译代码时候需要依赖的插件信息}三、使用命令编译JS代码基本上所有支持命令操作的模块都有一个命令babel –help/babel -h 查看帮助babel -V 查看版本号babel -o 把某一个JS文件中的ES6代码进行编译babel -d 把某一个文件夹中所有的JS文件中的ES6代码进行编译babel -w 监听文件中代码的改变,当代码改变后,会自动进行编译
ES6增加的语法
let&&const
let与var的区别
let 变量名=变量值使用let创建变量和使用var创建变量的区别
1、用var声明的变量会变量提升,用let声明的变量不会进行变量提升
用let创建变量
let xxx=xxx;
用let创建函数
let xxx=function(){}
创建自执行函数
;(function(){
})();
2、用let定义变量不允许在同一个作用域中重复声明一个变量(只要当前作用域中有这个变量,不管是用var还是用let声明的,再用let声明的话会报错:不能重复声明一个变量),但是可以重复定义(赋值)
let i=10;
let i=20;/会报错,
i=20;重复赋值不会报错
3、暂时性死区:在代码块内,使用let命令声明变量之前,该变量都是不可以使用的,
if (true) {
// TDZ开始
tmp = 'abc'; // ReferenceError,报错之后下面都不会输出
console.log(tmp); // ReferenceError,报错之后下面都不会输出
let tmp; // TDZ结束
console.log(tmp); // undefined
tmp = 123;
console.log(tmp); // 123
}
//下面也会报错出现TDZ
console.log(typeof x); // ReferenceError
let x;
//作为比较如果一个变量根本没有被声明,使用typeof反而不会报错。
console.log(typeof x);// "undefined"
4、ES6语法创建的变量(let)存在块级作用域
[ES5]window全局作用域函数执行形成的私有作用域 [ES6]除了有ES5中的两个作用域,ES6中新增加块级作用域(我们可以把块级作用域理解为之前学习的私有作用域,存在私有作用域和作用域链的一些机制)ES6中把大部分用{}包起来的都称之为块级作用域;
const
const细节知识点和let类似const声明的常量只要声明就必须赋值,而且变量的值是一定的,不能被修改;
注意:并不是变量的值不得改动,而是变量指向的那个内存地址不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指针,const只能保证这个指针是固定的,至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。const声明的变量也存在暂时性死区,即只能在声明的位置之后使用;
JS中创建变量的方式汇总
[ES5]
var :创建变量function:创建函数ES5中创建变量或者函数:存在变量提升,重复声明等特征;[ES6]
let创建变量const:ES6中创建常量ES6中创建的变量或者常量:都不存在变量提升,也不可以重复声明,而且还存在块级作用域;class:创建一个类import:导入 class Animal{
constructor(name,age){this.name = name; this.age = age; } function Animall(){
this.name = name; this.age = age; }
ES6中的解构赋值
按照原有值的结构,把原有值中的某一部分内容快速获取到(快速赋值给一个变量)
数组的解构赋值
解构赋值本身是ES6的语法规范,使用什么关键字来声明这些变量是无所谓的,如果不用关键字来声明,那么就相当于给window添加的自定义属性;(严格模式下必须使用关键字来声明,因为严格模式下不允许出现不用关键字声明的变量;),如果解构不到值,那么变量的值就是undefined;
let [a,b,c]=[12,23,34];
var [d,e,f]=[35,41,63];
console.log(a,b,c)//12,23,34;
console.log(d,e,f)//35,41,63;
[q,w,e]=[1,2,3];//相当于给window添加了三个属性:q,w,e值分别为1,2,3;(严格模式下会报错)
多维数组的解构赋值,可以让我们快速的获取到需要的结果
let [a,b,c]=[[45,36],12,[23,43,[1,2[4,[8]]]]23,34];
console.log(a)//[45,36]
console.log(b)//12
console.log(c)//[23,43,[1,2,[4,[8]]]]
//数组中不需要解构的值可用逗号(,)空开,一个逗号代表空开一项
let [,,,A]=[12,23,45];
console.log(A)//undefined
let [,,B]=[12,23,45]
console.log(B)//45
在解构赋值中,支持扩展运算符即…,只要用了扩展运算符,就相当于新生成了一个数组或者对象,如果解构不到值的话,新生成的数组或者对象为空,而不是undefined,但是扩展运算符必须放在末尾
let [a,...c]=[12,1,4,83,34];
console.log(a)//12
console.log(c)//[1,4,83,34];
let [a,...b,c]=[12,1,4,83,34];//会报错,扩展运算符只能放在末尾;
对象的解构赋值
对象的简洁表示法:const foo = 'bar';const baz = {foo};baz // {foo: "bar"}// 等同于const baz = {foo: foo};对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
let { foo, bar } = { foo: "aaa", bar: "bbb" };
foo // "aaa"
bar // "bbb"
如果变量名与属性名不一致,必须写成下面这样。
let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
baz // "aaa"
真正被赋值的是后者,而不是前者。
let obj = { first: 'hello', last: 'world' };
let { first: f, last: l } = obj;
f // 'hello'
l // 'world'
first//error: first is not defined
如果要将一个已经声明的变量用于解构赋值,必须非常小心。
// 错误的写法
let x;
{x} = {x: 1};//会报错
因为 JavaScript 引擎会将{x}理解成一个代码块,从而发生语法错误。只有不将大括号写在行首,避免 JavaScript 将其解释为代码块,才能解决这个问题。
// 正确的写法
let x;
({x} = {x: 1});
放在圆括号当中就可以避免 JavaScript 将其解释为代码块。
解构赋值中支持指定默认值
let [foo = true] = [];
console.log(foo);// true
let [x, y = 'b'] = ['a']; // x='a', y='b'
let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'
var {x: y = 3} = {};
y // 3
var {x: y = 3} = {x: 5};
y // 5
解构赋值的作用
1、快速交换两个变量的值
let a=12;
let b=13;
[a,b]=[b,a];
console.log(a);//13
console.log(b);//12
2、可以接收函数返回的多个值
let fn = function () {
let a = 12,
b = 13,
c = 14;
return [a, b, c];
};
let [a,b,c] = fn();
console.log(a, b, c);//=>12 13 14
… 的三种身份:扩展运算符、展开运算符、剩余运算符
1、扩展运算符(注意,在解构赋值中,叫做扩展运算符,只能放在末尾)
只要用了扩展运算符,就相当于新生成了一个数组或者对象,如果解构不到值的话,新生成的数组或者对象为空,而不是undefined,但是扩展运算符必须放在末尾
数组中的扩展运算符
let [a,b,...c]=[12,1,4,83,34]
console.log(a);//12
console.log(b);//1
console.log(c);//[4,83,34]
对象中的扩展运算符
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
console.log(x);//1
console.log(y );//2
console.log(z );//{ a: 3, b: 4 }
2、剩余运算符
function(...arg){
...arg就相当于剩余运算符,可以把传递的所有参数都获取到,而且获取到的是一个数组
}
3、展开运算符
function fn1(){
}
function fn2(){
fn1(...arguments)
...arguments:这里的...就相当于展开运算符,把arguments展开,把里面的每一项分别传递给fn1当作参数,然后让fn1执行;
}
箭头函数
两种写法:1、表达式 2、函数体
表达式:
1.let fn=p=>p; 等价于 var fn=function(p){return p};
2.let fn=()=>n; 等价于 var fn=funciton(){return n};
3.let fn=(n,m)=>n+m;等价于 var fn=function(n,m){return n+m};
函数体:
let fn=(n,m)=>{
var total=n+m;
return total;
}
1、箭头函数中不支持arguments,但是用 剩余运算…arg 代替了arguments,arg是一个数组,可以直接使用数组方法
let obj={
name:'obj',
fn(){
//此方法的属性名为fn,属性值为一个函数,和下面的sum写法是一样的;
},
sum:function () {
}
};
let fn = (...arg)=> {
/console.log(arguments);//=>Uncaught ReferenceError: arguments is not defined
/=>不支持arguments,我们使用ES6中的剩余运算符...来获取传递的进来的所有参数值(优势:使用剩余运算符接收到的结果本身就是一个数组,不需要再转换了)
/console.log(arg instanceof Array);//=>true
return eval(arg.join('+'));
};
//=>也可以把FN简写成以下方式
//let fn = (...arg)=> eval(arg.join('+'));
console.log(fn(10, 20, 30, 40));
2、箭头函数中的this问题,可以默认为箭头函数中没有this,在箭头函数中出现的this都是宿主环境中(即上级作用域中)的this,与箭头函数点之前的执行主体没有任何关系;
ES6中的类和继承
ES6中创建类和实例用class,创建出来的类不存在变量提升;ES5中创建类和实例,以及如何禁止用户把类当做普通函数执行:new.targetif (typeof new.target === 'undefined') {throw new SyntaxError(`当前Person不能作为一个普通函数执行,请使用new Person来执行~~`);}
class Father {//定义一个类;
constructor(name, age) {//构造函数定义实例的私有属性
this.name = name;
this.age = age;
}
getName() {//公有的函数和方法
console.log(this.name + "的年龄是" + this.age + "岁了");
}
static like() {//static后面写的是把Father当
模版字符串
模版字符串,也是字符串,可以直接使用字符串中的方法;模版字符串的空格和换行,都是被保留的,如果想要消除空格可以使用trim方法;$('#list').html(`<ul><li>first</li><li>second</li></ul>`.trim());模版字符串中可以嵌入变量,需要将变量写在${}中,大括号内部可以放入任意的 JavaScript 表达式,可以进行运算,以及引用对象属性。let x = 1;let y = 2;`${x} + ${y} = ${x + y}`// "1 + 2 = 3"`${x} + ${y * 2} = ${x + y * 2}`// "1 + 4 = 5"let obj = {x: 1, y: 2};`${obj.x + obj.y}`// "3"模板字符串之中还能调用函数。function fn() {return "Hello World";}`foo ${fn()} bar`// foo Hello World barES6中新增加的迭代for of
forEach,for,for in,for of的区别forEach:不支持返回值,只是普通的循环遍历for in:key输出的值为字符串类型,包括把数组当成对象添加的属性也可以遍历出来for of:只返回具有数字索引的属性。这一点跟for…in循环也不一样。(不能遍历对象)
let arr = [3, 5, 7];
arr.foo = 'hello';
for (let i in arr) {
//for in是把arr当成对象遍历,i是属性名,包括arr的私有属性
console.log(i); // "0", "1", "2", "foo"
}
for (let i of arr) {
//for of是把arr当成数组遍历,i是数组中的每一项
console.log(i); // "3", "5", "7"
}
for of循环不会返回数组arr的foo属性
如果只想拿到索引,可用keys()方法
for (let index of arr.keys()) {
console.log(index);
}
// 0
// 1
// 2
如果两个都想拿到,可用entries()方法
for (let (index, elem) of arr.entries['ɛntrɪs]()) {
console.log(index, elem);
}
// 0 "3"
// 1 "5"
// 2 "7"
ES6中的模块导入和导出
//=>A模块(在A模块中导入B模块)
import Temp,{lib} from "./B";//=>把导入的Temp中的部分属性方法进行解构赋值
new Temp().init();
lib();//=>Temp.lib()
//=>B模块(导出)
export default class Temp {
init() {
console.log(`hello world`);
}
static lib(){//=>Temp.lib
}
}