本文是学习陆老师的《python全栈工程师 - web开发前端基础》课程的笔记,欢迎学习交流。同时感谢陆老师的精彩传授!
一、课程目标
- es6版本介绍
- es6新增语法
二、详情解读
2.0.ES6版本简介
自从2009年ES5版本出来后,各种大神的加入让标准近乎难产,大家都希望在下一个版本里加入自己的建议功能,最后到2015处,终于搞定出了一个新的版本,命名为ECMAScript 2015,也就是ES6初稿,最后在2016年定为ES6版本。
由于浏览器的版本复杂性,es6的所有特性并不能在所有浏览器上获得全部支持,所以用es6写的语法可能需要先用工具转换为es5语法。
2.1.let与const
新的变量定义关键字:
1.let定义一个变量
2.const定义一个常量
3.let与const定义的变量作用域范围是块级作用域{}
4.对一个变量不能重复声明
5.在es6里,const定义的常量是不能改变值的
代码示例:
// let声明
let a = 10
// 不能重复定义,在es6里,下面这个声明会报错
let a = 100
//const 定义一个常量,常量一般用大写,这是约定俗成的写法
const A = 10
// 定义常量后不能再给a赋值
A = 20
// 引用型的可以修改值
const OBJ = {}
OBJ.name = "luxp"
//let与const 是块级作用域
// 只在距离最近的{}内生效
condition = true
if (condition){
const B = 10
for (i=0; i<2;i++){
//可以访问B
console.log(i+B)
}
}
// 外面无法访问块级作用域,就像全局无法访问局部变量一样
console.log(B)
i = 0
while (i<2){
if (condition){
let C = 10
}
i++
// 外层块级无法访问内层块级作用域变量
console.log(i-C)
}
//let不支持变量提升
function myFun(){
// var myname
console.log(myname)
// var myname = "luxp" 如果是这种方式,则不会报错,只会输出undefined
let myname = "luxp" // 这种会报错myname is not defined
}
myFun()
2.2.变量解构赋值
类似python解包从元组,列表以及对象中提取值,对变量进行赋值,被称为解构
代码示例:
[x,y,z]=["a","b","c"];
[x,y,z]=["a","b","c"];
//嵌套数组的解构
// 按照位置一一对应
[a,b,c,d] = [1,2,[3,4],5];
[a,b,[c1,c2],d] = [1,2,[3,4],5]
[foo, [bar, baz]] = [1, [[2], 3]]
[foo, [[bar], baz]] = [1, [[2], 3]];
//空缺变量:会跳过空缺的部分,还是按照位置对应解构
// 这种空缺变量在python里是不允许的,但是在js里是可以的
[a1,b1,,d1] = [1,2,[3,4,5],6];
[, , third] = ["foo", "bar", "baz"]; // third baz
[x1, , y1] = [1, 2, 3]; // x 1;y 3
//... 剩余操作符
// 剩余操作符后,不管有值没值,它都是一个数组,
// 比如下面的z2没值,则是空数组
[head, ...tail] = [1, 2, 3, 4]; // head 1; tail [2,3,4]
[x2, y2, ...z2] = ['a']; // x 'a';y undefined ; z []
//多余变量
// 多出来的变量,没有值,则会是undefined,而不会报错
// 下面的e的值是undefined
[a,b,c,,e] = [1,2,[3,4]];
//事实上只要某种数据解构具有Iterator接口,都可以采用数组形式的解构赋值
//对于Set结构,也可以使用数组的解构赋值
[x, y, z] = new Set(['a', 'b', 'c']);
// 字符串也可以按照顺序赋值给变量
// a = 'h', b = 'e', c = 'l'
[a,b,c] = "hello";
// 不能用可迭代的值,报错
[foo] = 1;
[foo] = false;
[foo] = NaN;
[foo] = undefined;
[foo] = null;
[foo] = {};
//解构赋值允许指定默认值
[foo = true] = [];
[a,b,c,d]= [1,2,3,4];
[a,b,c,d=5] = [1,2,3];
[x, y = 'b'] = ['a']; // x='a', y='b'
// 只有当解构赋值为undefined或者为空时,值才会为默认值
// 如果下面的undefined改为false, null, NaN等不是undefined的值,则y都不会为默认值'b'
[x, y = 'b'] = ['a', undefined]; // x='a', y='b'
//对象解构
obj = new Object();
obj.uname = "abc";
obj.uid = 123;
// 如果是以{开头的,则前面要加 let,否则会报错
// 注意对象属性与赋值的位置,别写反了
let { uname:name,uid:id } = obj;
// 如果不想加let,则加有小括号也可行,比如下面的语句可正常执行
({ uname:name,uid:id } = obj)
console.log(name);
//函数参数解构
// 与python的*,**作用类似
var arr=[1,2];
function fun([a,b]){
console.log("a:"+a);
console.log("b:"+b);
}
fun(arr);
var obj = {
uid : 123,
uname:"james"
}
function show({uid, name}){
console.log(uid);
}
show(obj)
2.3.箭头函数
箭头函数与python中的lambda函数类似
1.匿名函数
2.不需要return
//相当于一个匿名函数 简化了函数的定义
// 与python的lambda x,y: x+y类似
// 无形参
()=>"hello world" // 定义了一个箭头函数
(()=>"hello world")() // 箭头函数的执行
myFun = () =>"hello";
console.log(myFun())
// 相当于
myFun = function(){
return "hello world"
}
myFun = (a=3)=>a**2
// 相当于
function myFun(a=3){
return a**2;
}
myFun = (a,b=3) => a*b
//相当于
function myFun(a,b=3){
console.log(a*b);
return a*b
}
//关于this的问题
//箭头函数可以保持this指向
// 普通函数
function func(){
return "hello world"
}
var obj = {
x:1,
func:function(){
console.log(this.x);
},
test:function(){
//this指向obj
console.log(this)
console.log(this.func());
that = this
setTimeout(function(){
//this指向window
console.log("普通匿名函数this")
console.log(this);
try{
// 隔了3秒后,this指定了全局对象,而全局里并无函数func(),
// 所以将this赋值给that指向当前作用域,这是普通函数的解决方案
console.log(that.func());
} catch(e){
console.log(e)
}
},3000)
}
}
obj.test();
//箭头函数
var obj = {
x:1,
func:function(){
console.log(this.x);
},
test:function(){
//this指向obj
console.log(this)
console.log(this.func());
setTimeout(()=>{
//this指向obj
// 箭头函数this则会指向当前对象实例
console.log("箭头函数this")
console.log(this);
console.log(this.func());
},3000)
}
}
obj.test();
2.4.集合数据
与python中的集合概念一样:
一组不包含重复值的数据组合
mySet = new Set([1,2,3,3])
ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
Set 本身是一个构造函数,用来生成 Set 数据结构。
mySet = new Set()
mySet1 = new Set([1,2,3])
mySet2 = new Set([3,2,1])
// 注意:这里与python不一样的地方,mySet1==mySet2 返回false
console.log("mySet1==mySet2结果:",mySet1==mySet2)
mySet = new Set([2, 3, 5, 4, 5, 2, 2]);
mySet.add(7)
Set 实例的方法分为两大类:操作方法(用于操作数据)和遍历方法(用于遍历成员)。下面先介绍四个操作方法。
操作方法/属性 | 说明 |
---|---|
add(value) | 添加某个值,返回 Set 结构本身。 |
delete(value) | 删除某个值,返回一个布尔值,表示删除是否成功。 |
has(value) | 返回一个布尔值,表示该值是否为Set的成员。 |
clear() | 清除所有成员,没有返回值。 |
size | 成员总数 |
s = new Set();
s.add("one").add("two").add("two");
// 注意2被加入了两次 但是结果中只有一个2被添加进去,因为set本身就是一个没有重复数值的函数
console.log(s,s.size) // 2 Set.prototype.size:返回Set实例的成员总数。
//返回布尔值
console.log(s.has("one"))
console.log(s.has("one"))
console.log(s.has("one"))
//返回布尔值,表示删除是否成功
s.delete("two"); // 返回true,删除成功;false删除失败
console.log(s.has("two"))
forEach方法的参数就是一个处理函数。
该函数的参数与数组的forEach一致,依次为键值、键名、集合本身(上例省略了该参数)。
这里需要注意,Set 结构的键名就是键值(两者是同一个值),
因此第一个参数与第二个参数的值永远都是一样的。
s.forEach(function(key, val, set){
console.log(arguments)
console.log("key=>", key)
console.log("val=>", val)
}
)
2.5.for…of…
for…in…遍历的是索引
for…of…遍历的是值(这种遍历方式是es6新增的)
Set 结构的实例有四个遍历方法,可以用于遍历成员。
遍历方法 | 说明 |
---|---|
keys() | 返回键名的遍历器, 多余的 |
values() | 返回键值的遍历器 |
entries() | 返回键值对的遍历器,同时包括键名和键值,所以每次输出一个数组,它的两个成员完全相等 |
forEach() | 使用回调函数遍历每个成员 |
array = [1,2,3,4,5,6]
// 数组使用for in 与for of 区别
//索引
for (i in array){
console.log("array in:",i)
console.log("array[i]:",array[i])
}
// 值
for (i of array){
console.log("array of:", i)
}
//object使用for in 与for of 区别
obj = {
name:"luxp",
age : 28,
sex : "man"
}
//索引
for (i in obj){
console.log("obj in:",i)
console.log("obj[i]:",obj[i])
}
//对象不能直接使用for of遍历,下面的代码会报错
for ( i of obj){
console.log(i)
}
// 使用Object对象方法keys(), values()提取键值
for ( i of Object.keys(obj)){
console.log(i)
}
for ( i of Object.values(obj)){
console.log(i)
}
//集合没有索引,不能for in 遍历
set = new Set(['red', 'green', 'blue']);
// 下面的代码没有任何的输出,也不会报错
for (i in set){
console.log(i)
}
for (i of set) {
console.log(i);
}
//entries方法返回的遍历器,同时包括键名和键值,所以每次输出一个数组,它的两个成员完全相等
for (item of set.entries()) {
console.log(item);
}
Set用entries方法运行结果:(set的key和value是相等的,所以会输出两个)
2.6.class关键字
es6提供了创建对象的class语法,该语法仅仅是构造函数的语法糖
class newObject(){
construct(){}
doSome(){}
}
class只是原来构造函数的语法糖
类中的方法不需要function关键字声明
示例代码:
function Person(name, age,sex) {
this.hands = 2
this.head = 1
this.name = name
this.age = age
this.sex = sex
this.work = function(){
console.log('咋的,我就是闲得慌!');
}
}
class Person {
constructor(name, age,sex) {
this.hands = 2
this.head = 1
this.name = name
this.age = age
this.sex = sex
}
work() {
console.log('咋的,我就是闲得慌!');
}
}
zhangsan = new Person("zhangsan", 18, "男")
console.log(zhangsan.work())
// 继承 extends关键字,表示Man继承自Person,super代表父类
class Man extends Person{
constructor(name,age,sex){
super(name, age, "男")
console.log("男人制造工厂")
}
work(){
console.log("咋的,还能吃软饭么?!")
}
}
lisi = new Man("lisi", 28, "男")
运行结果:
2.7.模版字符串
模版字符串相当于python的格式化字符串的简单点位符使用
`${val} is ${bar}`
模版字符串,相当于格式化字符串
在字符串中用${变量名}作为占位符
示例代码:
name = "luxp"
sex = "男"
//非模版字符串拼接
string = name + "是一名" + sex + "性公民"
console.log(string)
string = `${name}是一名${sex}性公民`
console.log(string)
运行结果:
三、课程小结
- 学习了什么是es6
- 学习了es6的新增语法