0 ES6基本语法
ES标准中不包含 DOM 和 BOM的定义,只涵盖基本数据类型、关键字、语句、运算符、内建对象、内建函数等通用语法。
本部分只学习前端开发中ES6的必要知识,方便后面项目开发中对代码的理解。
1 let声明变量
与我们的JavaScript中var声明变量有什么区别?
<1>作用域不同
{ var a = 0; // var声明的变量是全局变量 let b = 0; // let声明的变量是局部变量 } console.log(a); console.log(b); //b is not defined:b没有定义
<2>声明次数不同
// var可以声明多次 // let只能声明一次 var m = 1; var m = 2; let n = 3; let n = 4; //SyntaxError: Identifier 'n' has already been declared(语法错误:n已经声明过了) console.log(m); console.log(n);
<3>声明与使用顺序不同
// var 声明的变量会全局存储 // let 声明的变量只能在执行后才存储 console.log( x ); //没有报错,输出:undefined var x = "苹果"; console.log(y); //y is not defined(y没有定义) let y = "香蕉";
2 const声明常量
const 声明常量,为只读变量
1. 一旦声明之后,其值是不允许改变的
2. 一但声明必须初始化,否则会报错 SyntaxError: Missing initializer in const declaration(语法错误,声明常量丢失了初始化)
const PI = 3.14; PI = 3.1415; //Assignment to constant variable.(声明的是常量) console.log( PI );
3 解构赋值
解构赋值是对赋值运算符的扩展
它是一种针对数组或者对象进行模式匹配,然后对其中的变量进行赋值。
解构,顾名思义,就是将集合型数据进行分解,拆分,把里面的值逐一遍历获取
在代码书写上简洁且易读,语义更加清晰明了;也方便了复杂对象中数据字段获取
3.1 数组解构
var arr = [1,2,3]; // 传统的js let a = arr[0]; let b = arr[1]; let c = arr[2]; console.log(a,b,c); //es6的解构 var [x,y,z] = arr; console.log(x,y,z);
3.2 对象解构
var user = { username : "吕布", weapon:"方天画戟", horse:"赤兔马" }; // 传统的js let mingzi = user.username; let wuqi = user.weapon; let zuoji = user.horse; console.log("姓名:"+mingzi+",武器:"+wuqi+",坐骑:"+zuoji); //es6的解构 let {username,weapon,horse} = user; // 注意:解构的变量名必须是对象中的属性 console.log("姓名:"+username+",武器:"+weapon+",坐骑:"+horse);
4 模板字符串
模板字符串相当于加强版的字符串
用反引号 `,除了作为普通字符串,还可以用来定义多行字符串
还可以在字符串中加入变量和表达式
4.1 定义多行字符串
再见了,
let str = `hello,
你俩在哪呢?
心情不好,出来喝点啊!`;
console.log(str)
4.2 字符串插入变量和表达式
再见了,字符串的拼接用 +
let name = `吕布`; let age = 24; // 传统的拼接字符串 var info1 = "我叫:"+ name +",我今年"+age+"岁!"; console.log(info1); // es6的拼接字符串 var info2 = `我叫:${name},我明年${age+1}岁!`; console.log(info2);
4.3 字符串中调用函数
还能这么玩
function test(){ return "吃喝玩乐"; } let str = `悲催的人生,从${test()}开始`; console.log( str );
5 声明对象简写
定义对象的时候,可以用变量名作为属性名
let name = `吕布`; let age = 28; //传统 let user1 = { name : name, age : age }; console.log(user1); //es6新语法中的简写 let user2 = {name,age}; console.log(user2);
6 定义方法简写
// 传统 let user1 = { say : function(){ console.log("大家好!"); } }; user1.say(); //es6 let user2 = { say(){ console.log("大家好啊!"); } }; user2.say();
7 对象拓展运算符
拓展运算符 {...} 将参数对象中所有可以遍历的属性拿出来,然后拷贝给新对象
7.1 拷贝对象(深拷贝)
科幻电影中的一滴血,就可以制作出一个完全一模一样的克隆人
let user1 = { name:"项羽", age:34 }; let user2 = {...user1}; // 深拷贝(克隆) console.log(user1); console.log(user2);
7.2 合并对象
吞噬合并(两个对象合并成一个对象)
let user1 = { name:"项羽", age:34 }; let user2 = {head:"诸葛亮"}; let user = {...user1,...user2}; console.log( user );
8 函数的默认参数
形参处已声明,但不传入实参会怎样?
function test(name , age = 18){ console.log(`我叫${name},我今年${age}岁`); } test("吕布",33); //我叫吕布,我今年33岁 test("貂蝉"); //我叫貂蝉,我今年18岁 test("关羽",null); //我叫关羽,我今年null岁 test("马超",""); //我叫马超,我今年岁 test("张飞",undefined); //我叫张飞,我今年18岁
9 函数的不定参数
定义方法时,不确定有几个参数?
function test( ...arg ){ console.log(`传入了${arg.length}个参数`); for(var i = 0 ;i<arg.length;i++){ console.log(arg[i]); } } test(1); test(1,2); test(1,2,3,4,5,6); test(); test("郭","嘉",28);
10 箭头函数
箭头函数提供了一种更加简洁的函数书写方式。基本语法是:参数 => 函数体
// 传统 var f1 = function(a){ return a*10; } console.log( f1(10) ); // es6 var f2 = a=>a*10; console.log( f2(20) ); // 当箭头函数一个参数时,()可以省略 // 当箭头函数没有参数或者有多个参数,要用()括起来 // 当箭头函数的函数体有多行语句,用{}括起来,表示代码块 // 当只有一条语句,并且需要返回时,可以省略{},结果会自动返回 var f3 = (a,b) => { let sum = a+b; return sum; }
console.log( f3(3,7) );
// 可以将f3进行简化
var f4 = (a,b) => a + b;
console.log( f3(11,22) );
11 Promise(了解)
用来解决回调函数的嵌套噩梦 (后面学习ajax才能更好的理解)
我们回顾一下嵌套噩梦:
使用promise解决掐架找人的噩梦:
找到一个人成功后,再继续找下一个人。逐渐形成了“队伍”
组建队伍的过程中,如果找某个人失败了,则“队伍”失败
其实有点类似“击鼓传花”的游戏,一个成功拿到花之后,才能传递给下一个人。依次类推!
setTimeout(()=>{ console.log(1); setTimeout(()=>{ console.log(2); setTimeout(()=>{ console.log(3); setTimeout(()=>{ console.log(4); },1000); },1000); },1000); },1000);
使用promise
next = n => //Promise的构造函数接收一个参数,是函数, //并且传入两个参数:resolve(异步操作执行成功后的回调函数),reject(异步操作执行失败后的回调函数) new Promise(function(resolve, reject) { setTimeout(function() { resolve(n); }, 1000); }); next(1) .then(res => { // 成功 console.log(res); return next(2); //在then方法中调用的next方法,一定要用return ,否则不会通过resolve把数据往下传递 }) .then(res => { console.log(res); return next(3); }) .then(res => { console.log(res); }) .catch(() => { //处理失败:catch方法的第二个参数是失败的回调 console.log("出错啦!"); });
12 模块化
如果在a.js文件中定义了5个方法,现在b.js文件中想使用a中的5个方法,怎么办?
java语言的做法是import引入之后,就能使用了。es6的模块化,就是这个过程
将一个js文件声明成一个模块导出之后,另一个js文件才能引入这个模块
每一个模块只加载一次(是单例的), 若再去加载同目录下同文件,直接从内存中读取。
12.1 传统的模块化
创建user.js文件
function addUser(name){ return `保存${name}成功!`; } function removeUser(id){ return `删除${id}号用户!`; } // 声明模块并导出 // module.exports={ // save:addUser, // delete:removeUser // } // 声明模块导出的简写 module.exports={ addUser, removeUser }
test.js
let user = require("./user.js"); //引入user模块 console.log( user ); let result1 = user.addUser("吕布"); let result2 = user.removeUser(101); console.log(result1); console.log(result2);
12.2 ES6的模块化
user.js
let name = "老孙"; let age = 66; let fn = function(){ return `我是${name}!我今年${age}岁了!`; } // 声明模块并导出 export{ name, age, fn }
test.js
import {name,age,fn} from "./user.js" console.log(name); console.log(age); console.log(fn);
运行test.js,报错:SyntaxError: Unexpected token { (语法错误,在标记{的位置 )
原因是node.js并不支持es6的import语法,我们需要将es6转换降级为es5!
(见13)
13 babel环境
babel是一个广泛使用的转码器,可以将ES6代码转为ES5代码,从而在现有的环境中执行。
这意味着,你可以现在就用 ES6 编写程序,而不用担心现有环境是否支持
13.1 安装babel客户端环境
创建新目录 lagou-babel,在终端中打开,运行命令:
npm install --global babel-cli
查看版本
babel --version
如果报错1:(win7系统中)
'babel' 不是内部或外部命令,也不是可运行的程序或批处理文件。(babel命令在当前系统中不被认可)
由于babel是通过npm安装,所以babel会默认安装到 E: epo_npm
在 E: epo_npm 这个目录下,进入dos命令,执行 babel --version, 如果是成功的,说明babel 已经安装成功
但是在vscode的终端中打不开,那么只可能是两个原因:
<1>环境变量没有配置
系统环境变量中 path中加入 ;E: epo_npm;
在任意位置进入dos窗口,babel --version可以了,说明环境变量配置成功
<2>vscode关掉,重新以“管理员身份运行 ”
如果报错2:(win10系统中)
windows10默认禁止运行有危险的脚本,修改一下系统策略就好了
开始菜单-> Windows PowerShell (切记要以管理员身份运行),输入代码
set-ExecutionPolicy RemoteSigned
现在,就可以看版本号了。
13.2 安装转码器
1. 创建lagou-babel专属目录,在其中初始化项目
npm init -y
2. 创建babel配置文件 .babelrc ,并输入代码配置:
{ "presets": ["es2015"], "plugins": [] }
3. 安装转码器
npm install --save-dev babel-preset-es2015
4. 转码
创建dist目录,用来存放转码后的文件
babel user.js --out-file .distuser.js
或
babel user.js -o .distuser.js
5. 运行转码后的文件
node .dist est.js
14 ES6模块化的另一种写法
14.1 as的用法
user.js:如果你不想暴露模块当中的变量名字,可以通过as来进行操作:
let name = "老孙"; let age = 66; let fn = function(){ return `我是${name}!我今年${age}岁了!`; } // 声明模块并导出 export{ name as a, age as b, fn as c }
test.js
import {a,b,c} from "./user.js"; console.log(a); console.log(b); console.log( c() );
也可以接收整个模块
test.js
import * as info from "./user.js"; // 通过*来批量接收,as来指定接收的名字 console.log(info.a); console.log(into.b); console.log( into.c() );
14.2 默认导出
可以将所有需要导出的变量放入一个对象中,然后通过default export进行导出
/*****************导出****************************/ export default{ name:"老孙", eat(){ return "吃点啥!"; } } /*****************导入****************************/ import p from "./person.js"; console.log( p.name, p.eat() );
14.3 重命名export和import
如果导入的多个文件中,变量名字相同,即会产生命名冲突的问题, 为了解决该问题,ES6为提供了重命名的方法,当你在导入名称时可以这样做:
/*******************student1.js**************************/ export let name = "我是来自student1.js"; /*******************student2.js************************/ export let name = "我是来自student2.js"; /*******************test_student.js************************/ import {name as name1} from './student1.js'; import {name as name2} from './student2.js'; console.log( name1 ); // 我是来自student1.js console.log( name2 ); // 我是来自student2.js
15 练习