目录
简介
node.js安装
babel转码器
let命令
const命令
解构对象
字符串扩展
新增方法:
数组扩展
扩展运算符
伪数组
对象扩展
属性的简介表示法
属性名表达式
对象的扩展运算符
函数扩展
箭头函数
使用注意
Set数据结构
基本用法
size属性
特有方法
Promise对象
基本用法
异步加载图片资源
重点:Promise对象进行异步解决时,会线程阻塞,直到调用了resolve()或者reject()才会继续执行
Async和await
Class
基本语法
属性与方法
Class的继承
重点:子类需要先调用父类的构造方法,将父类构建出来,才能实例化自己
简介
es6是js的规范,而js是es6的实现
名称详解
ECMAScript 6(以下简称 ES6)是 JavaScript 语言的标准,在 2015 年 6 月发布。它的目标,是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。
版本 | 官方名称 | 发布日期 |
ES1 | ECMAScript 1 | 1997 |
ES2 | ECMAScript 2 | 1998 |
ES3 | ECMAScript 3 | 1999 |
ES4 | ECMAScript 4 | 从未发布过 |
ES5 | ECMAScript 5 | 2009 |
ES5.1 | ECMAScript 5.1 | 2011 |
ES6 | ECMAScript 2015(ECMAScript 6) | 2015 |
ES7 | ECMAScript 2016 | 2016 |
ES8 | ECMAScript 2017 | 2017 |
... | ... | ... |
因此,ES6 既是一个历史名词,也是一个泛指,含义是 5.1 版以后的 JavaScript 的下一代标准,涵盖了 ES2015、ES2016、ES2017 等等
node.js安装
Nodejs诞生于2009年,主攻服务器方向,使得利用JavaScript也可以完成服务器代码的编写
Nodejs官网
Node.js
Nodejs的安装与一般软件一样
大量的库
在安装Nodejs的同时,会附带一个npm命令,npm 是Node的包管理工具,这样正是接下来我们要用到的
npm 的简单结构有助于 Node.js 生态系统的激增,现在 npm 仓库托管了超过 1,000,000 个可以自由使用的开源库包
npm镜像安装(使用国内的镜像命令式CNPM)
由于服务器在国外,所以下载速度比较慢,我们可以用国内的 镜像
阿里镜像地址
npmmirror 镜像站
在命令行运行如下命令即可
npm install -g cnpm --registry=https://registry.npmmirror.com
看到如下信息,代表安装成功
babel转码器
Babel 是一个广泛使用的 ES6 转码器,可以将 ES6 代码转为 ES5 代码,从而在老版本的浏览器执行。这意味着,你可以用 ES6 的方式编写程序,又不用担心现有环境是否支持
浏览器支持性查看
https://caniuse.com/
Babel官网
https://babeljs.io/
转码示例
原始代码用了箭头函数,Babel 将其转为普通函数,就能在不支持箭头函数的 JavaScript 环境执行了
// 转码前
input.map(item => item + 1);
// 转码后
input.map(function (item) {
return item + 1;
});
Babel安装流程
第一步:安装 Babel
npm install --save-dev @babel/core第二步:配置文件.babelrc
Babel 的配置文件是.babelrc,存放在项目的根目录下。使用 Babel 的第一步,就是配置这个文件。
该文件用来设置转码规则和插件,基本格式如下
{
"presets": [],
"plugins": []
}第三步:安装转码规则集
presets字段设定转码规则,官方提供以下的规则集,你可以根据需要安装
npm install --save-dev @babel/preset-env第四步:将规则加入.babelrc
{
"presets": [
"@babel/env"
],
"plugins": []
}安装Babel命令行转码工具
Babel 提供命令行工具@babel/cli,用于命令行转码
npm install --save-dev @babel/cli
基本用法如下
# 转码结果输出到标准输出
$ npx babel 被转码文件路径
# 转码结果写入一个文件
# --out-file 或 -o 参数指定输出文件
$ npx babel 被转码文件路径 --out-file 转码成的文件名
# 或者
$ npx babel 被转码文件路径 -o 转码成的文件名
# 整个目录转码
# --out-dir 或 -d 参数指定输出目录
$ npx babel src --out-dir lib
# 或者
$ npx babel src -d lib
let命令
let是一种声明变量的关键字,用法类似于var,但是其所声明的变量具有块级作用域。
let块级作用域
<script> { let h1 = "hello"; var h2 = "world"; } console.log(h2); console.log(h1); </script>
let不存在变量提升
<script> console.log(h2); console.log(h1); let h1 = "hello"; var h2 = "world"; </script>
let不能重复声明
<script> var a = 1; var a = "1"; let b = 1; let b = 2; </script>
const命令
const命令用于修饰常量,const修饰的常量在定义时需要初始化,并且不能修改值
const和let一样,具有块级作用域,不存在变量提升,不能重复定义
定义时必须初始化
<script> const a; </script>
不能修改值
<script> const a = 1; a = 2; </script>
解构对象
就是将对象中的指定key进行解析出来,这样我们就可以直接使用该key获得对应的value,
而不需要使用对象.key取值
<script> let {name,age} = {name:"zhangsan",age:16}; console.log(name); console.log(age); </script>
字符串扩展
字符串遍历的方式
of左边定义变量,右边代表被遍历的字符串
<script> for(let i of "hello world"){ console.log(i); } </script>
模板字符串
以往我们在标签中嵌入变量需要通过拼接的方式,而模板字符串可以很轻松的为我们解决,只需要通过反引号(` `)标识,然后在里面正常写标签,需要嵌入变量时只需要通过
${变量名}即可嵌入变量
<script> var s1 = "url"; console.log("<a href='"+ s1 +"'></a>"); console.log(`<a href="${s1}"></a>`); </script>
新增方法:
includes(),startsWith(),endsWith()
<script> //includes(),判断字符串中是否包含子字符串 console.log("----------includes()----------"); console.log("hello world".includes("wor")); //startsWith(),判断字符串是否以子字符串开头 console.log("----------startsWith(),endsWith()----------"); console.log("hello world".startsWith("wor")); console.log("hello world".startsWith("hel")); //endsWith(),判断字符串是否以子字符串结尾 console.log("hello world".endsWith("wor")); console.log("hello world".endsWith("ld")); </script>
trimStart(),trimEnd()
<script> console.log("----------trimStart(),trimEnd()----------"); //trimStart(),去除字符串头部的空格 console.log(" ni hao shi jie ".trimStart()); //trimEnd(),去除字符串尾部的空格 console.log(" ni hao shi jie ".trimEnd()); </script>
repeat()
<script> //repeat(),重复字符串n次 console.log("----------repeat()----------"); console.log("abc|".repeat(2));//2,代表重复两次 </script>
padSstart(),padEnd()
<script> console.log("----------padStart(),padEnd()----------"); //padStart(),补全长度,如果长度不足指定长度,用指定字符串在原字符串头部补全 console.log("ni hao shi jie".padStart(20,"-")); //padEnd(),补全长度,如果长度不足指定长度,用指定字符串在原字符串尾部补全 console.log("ni hao shi jie".padEnd(20,"-")); </script>
数组扩展
扩展运算符
通过在数组名前面添加(...),即可将数组转为用逗号分隔参数序列
打印时比较特殊,以空格分隔
<script> var arr = [1,2,3,4,5,6]; console.log(...arr); </script>
通过扩展运算符我们可以实现,两个数组的合并以及判断数组的最大值
<script> var arr = [1,2,3]; var arr1 = [10,20,30] console.log([...arr,...arr1]);//数组合并 console.log(Math.max(...arr));//数组最大值 </script>
伪数组
伪数组类似数组,但是他并不是数组,他可以使用数组的引用方式和length属性,但是不能使用数组的方法
伪数组有三种:
- arguments
- 元素集合
- 类似数组的对象
arguments
<script> function add(){ console.log(arguments); console.log(arguments[0]); console.log(arguments[1]); console.log(arguments[2]); } add(1,2,3) </script>
元素集合
<body> <div class="1"> <div class="2"></div> </div> </body> <script> let div = document.querySelectorAll("div"); console.log(div[0]); console.log(div[1]); </script>
类似数组的对象
<script> var user = { '0':"a", '1':"b", '2':"c", length:3 } console.log(user[0]); console.log(user[1]); console.log(user[2]); </script>
Array.from()
该方法的作用是将伪数组转为真正的数组
<body> <div class="1"> <div class="2"></div> </div> </body> <script> // arguments function add(){ console.log(Array.from(arguments)); } add(1,2,3) // 元素集合 let div = document.querySelectorAll("div"); console.log(Array.from(div)); // 类似数组的对象 var user = { '0':"a", '1':"b", '2':"c", length:3 } console.log(Array.from(user)); </script>
对象扩展
属性的简介表示法
当属性名和变量名相同时,即可不需要使用key:value的方式进行赋值,具体如下:
<script> var name = "zhangsan"; var user = { name, age:16 } console.log(user); </script>
属性名表达式
通过[表达式]的方式定义属性名,方括号中可以使用表达式
<script> var name = "zhangsan"; var user = { ["a"+"b"+name]:name, age:16 } console.log(user); </script>
对象的扩展运算符
通过(...对象名)的方式将对象转为key:value,key:value...的序列
<script> var name = "zhangsan"; var user = { name, age:16 } var user2 = { ...user } console.log(user2); </script>
函数扩展
箭头函数
在es6中新增了一种函数的表达方式,就是箭头函数,如果你学过java应该可以很轻松的理解,箭头函数就像java中lambda表达式一样只是把->变为了=>,如果你没有学过java也没有关系我们可以通过案例来了解:
<script> //语法: //(参数) => { function code... } //注意:如果只有一个参数可以省略小括号,但是如果有多个参数,括号不允许省略 //箭头右侧的大括号也是一样的原理,只有一条语句可以直接省略 var fun = function(){ console.log("这是一个普通函数!"); } var fun2 = () => {console.log("这是一个箭头函数!")}; var fun3 = a => console.log("只有一个参数,且只有一条语句!"+a); fun(); fun2(); fun3("\thello world!"); </script>
通过以上图片我们可以发现,箭头函数其实也就是将function变成了一个=>,通过参数=>{}的方式实现函数的定义
使用注意
对于普通函数来说,内部的this指向的是执行该方法的对象,但是箭头函数没有这一点,它没有自己的this对象,内部的this就是定义时上层作用域的this
<script> var user = { name:"zhangsan", age:16, getName:function(){ console.log(this.age); }, getName2:() => console.log(this.age) } user.getName(); user.getName2(); </script>
Set数据结构
Set结构类似Java中的Set集合,该结构中存储的数据有序不可重复
基本用法
1、新增数据
<script> var set = new Set(); set.add(1); set.add(2); console.log(set); </script>
2、数组去重
<script> var set = new Set([1,2,2,3,4,4]); console.log([...set]); </script>
3、字符串去重
<script> var set = new Set("hello world!!!"); var str = [...set].join(""); console.log(str); </script>
size属性
该属性可以获得该对象中存放的元素个数
<script> var set = new Set("hello world!!!"); console.log(set.size); </script>
特有方法
add()
set 添加方法
var mySet = new Set(); mySet.add("5") console.log(mySet);
delete()
删除某个值,返回一个布尔值,表示删除是否
var mySet = new Set(); mySet.add("5") var flag = mySet.delete("5"); console.log(flag); // true
has()
返回一个布尔值,表示该值是否为Set的成员
var mySet = new Set(); mySet.add("5") var flag = mySet.has("5"); console.log(flag); // true
clear()
清除所有成员,没有返回值
var mySet = new Set(); mySet.add("5") mySet.clear(); console.log(mySet); // Set(0){size: 0}
Promise对象
promise对象时异步编程的一种解决方案,以往的异步编程往往需要用到回调函数,如果回调函数中又用到了回调函数此时就会有回调函数的层级嵌套,如果回调函数过多,就会导致代码可读性差
所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理
有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise对象提供统一的接口,使得控制异步操作更加容易
基本用法
ES6 规定,Promise对象是一个构造函数,用来生成Promise实例
Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由 JavaScript 引擎提供,不用自己部署
const promise = new Promise(function(resolve, reject) { //参数名不允许更改,必须叫这个名字 // ... some code if (/* 异步操作成功 */){ resolve(value); } else { reject(error); } });
Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。
promise.then(function(value) { // success }, function(error) { // failure });
异步加载图片资源
<body> <div id="img"> </div> </body> <script src="../Promise对象/jquery-3.6.1.min.js"></script><!-- 引入jquery --> <script> function loadImageByUrl(url){ const image = new Image(); const promise = new Promise(function(resolve,reject){ image.src = url;//设置图片路径 image.onload = function(){ resolve(image);//成功调用resolve(),并将image对象传进去 }; image.onerror = function(){ reject(new Error('Could not load image at'+url)); //失败调用reject,并传入错误信息 }; }); return promise;//返回promise对象 } loadImageByUrl("https://images.pexels.com/photos/13324150/pexels-photo-13324150.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2") .then(function(data){ $("#img").append(data);//成功显示图片 },function(error){ console.log(error);//失败显示失败信息 })
重点:Promise对象进行异步解决时,会线程阻塞,直到调用了resolve()或者reject()才会继续执行
Async和await
异步编程的时候,我们通常都是有一个执行链的,也就是说a1()执行完返回一个数据,然后a2()拿着a1()返回的执行,返回一条数据,a3()再拿着a2()返回的数据执行()......
但是因为这是异步编程,所以不能保证方法的顺序执行,所以此时就需要使用到Async,通过Async修饰函数,await关键字修饰语句,即可实现异步操作变为同步操作
没有加async和await
<script> function timemout(ms){ return new Promise(function(resolve,reject){ setTimeout(function(){ console.log("你好世界!"); resolve(); },ms); }) } timemout(500); console.log("hello world!"); </script>
加了async和await
<script> function timemout(ms){ return new Promise(function(resolve,reject){ setTimeout(function(){ console.log("你好世界!"); resolve(); },ms); }) } async function testTimeout(){ await timemout(500); await console.log("hello world!"); } testTimeout(); </script>
Class
类的由来
JavaScript 语言中,生成实例对象的传统方法是通过构造函数
function Point(x, y) { this.x = x; this.y = y; } Point.prototype.toString = function () { return '(' + this.x + ', ' + this.y + ')'; }; var p = new Point(1, 2);
ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类
基本上,ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已
基本语法
constructor()构造方法
constructor()方法是创建类时默认调用的方法,一个类必须有constructor(),如果没有定义则会默认添加无参构造方法
class Point { } // 等同于 class Point { constructor() {} }
类的实例
<script> class Point{ constructor(x,y){ this.x=x; this.y=y; } getPoint(){ console.log(`x:${this.x},y:${this.y}`); } } var point = new Point(1,2); point.getPoint(); </script>
属性与方法
实例方法
通过类的实例对象调用方法
class People{ say(){ console.log("Hello"); } } var p = new People(); p.say()
实例属性
实例属性指的是类的实例对象可调用的属性
class People{ constructor(name,age){ this.name = name; this.age = age; } say(){ console.log(this.name,this.age); } } var p = new People("iwen",20); p.say() console.log(p.name,p.age);
静态方法
类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”
class Person { static classMethod() { console.log("Hello"); } } Person.classMethod() // Hello var p = new Person(); p.classMethod() // p.classMethod is not a function
温馨提示
注意,如果静态方法包含this关键字,这个this指的是类,而不是实例。
class People { static getSay() { this.say(); } static say() { console.log('hello'); } say() { console.log('world'); } } People.getSay() // hello
静态属性
静态属性指的是 Class 本身的属性,即Class.propName
class People{} People.status = "等待" console.log(People.status);
Class的继承
基础用法
Class 可以通过extends关键字实现继承,让子类继承父类的属性和方法。extends 的写法比 ES5 的原型链继承,要清晰和方便很多
class Point { } class ColorPoint extends Point { }
ES6 规定,子类必须在constructor()方法中手动调用super(),否则就会报错,这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,添加子类自己的实例属性和方法。如果不调用super()方法,子类就得不到自己的this对象
class Point { constructor(x,y){ this.x = x; this.y = y; } getPoint(){ console.log(this.x,this.y); } } class ColorPoint extends Point { constructor(x,y,z){ super(x,y) this.z = z; } } let cp = new ColorPoint(10,20,30) cp.getPoint();