文章目录
学习资料
ES介绍
ES全称EcmaScript
,是脚本语言的规范
,而平时经常编写的JavaScript
是EcmaScript的一种实现
,所以ES新特性其实指的就是JavaScript的新特性
为什么要学习新特性?
- 语法简洁,功能丰富
- 框架开发应用
- 前端开发职位要求
let 声明变量
可以同时声明一个或多个
不能重复声明
块级作用域
块级作用域只能在代码块中有效
不存在变量提升
不影响作用链
const 定义常量
声明常量
注意事项
- 一定要赋初始值
- 一般常量使用大写(潜规则)
- 常量的值不能修改
- 块级作用域
- 对于数组和对象的元素修改,不算做对常量的修改,不会报错,因为引用地址没有发生改变,如果修改整个数组让其引用地址发生改变则会报错
变量的解构赋值
ES6 允许按照一定的模式从
数组
和对象
中提取值
,对变量
进行赋值
,这被称为解构赋值
数组解构赋值
对象解构赋值
模板字符串
ES6 引入新的声明字符串的方式 `` "" ''
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>模板字符串</title>
</head>
<body>
<script>
// ES6 引入新的声明字符串的方式 `` '' ""
// 1. 声明
let str = `我是一个字符串哦!`;
console.log(str,typeof str)
// 2. 内容可以直接出现换行符
let hh = `<ul>
<li>沈腾</li>
<li>玛丽</li>
</ul>`;
// 3. 变量拼接
let lovest = '沈腾';
let out = `${lovest}是我心中最搞笑的演员!`;
console.log(out)
</script>
</body>
</html>
简化对象写法
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>简化对象写法</title>
</head>
<body>
<script>
//ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法,这样的书写更加简洁。
let name = `尚硅谷`;
let change = function(){
console.log(`我们可以改变你!`)
}
// 老写法
const lowSchool = {
name: name,
change: change,
improve: function(){
console.log(`我们可以提高你的技能`)
}
}
// 简化写法
const newSchool = {
name,
change,
improve(){
console.log(`我们可以提高你的技能`)
}
}
console.log(lowSchool)
console.log(newSchool)
</script>
</body>
</html>
箭头函数
- 注意事项:
-
this
是静态
的,this
始终指向函数声明时所在作用域下的 this的值
-
- 不能作为构造实例化对象
-
- 不能使用
arguments
变量
- 不能使用
-
- 箭头函数的简写,当形参且只有一个的时候可以省略小括号;当代码体只有一条语句的时候可以省略花括号并且此时return必须省略,语句的执行结果就是函数的返回值
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>箭头函数</title>
</head>
<body>
<script>
// ES6 允许使用 箭头( => )定义函数
// 声明一个函数
// let fn = function(){
// }
let fn = (a,b) => {
return a + b;
}
// 调用函数
let result = fn(1,2);
console.log(result)
// 1. this 是静态的,this始终指向函数声明时所在作用域下的 this的值
function getName(){
console.log(this.name);
}
let getName2 = () => {
console.log(this.name)
}
// 设置 window 对象的 name 属性
window.name = `尚硅谷`;
const school = {
name: `ATGUIGU`
}
// 直接调用
getName();
getName2();
// call 方法调用
getName.call(school)
getName2.call(school)
// 2. 不能作为构造实例化对象
let Person = (name, age) => {
this.name = name;
this.age = age;
}
let me = new Person('xiao',30);
console.log(me)
// 3. 不能使用 arguments 变量
let fn1 = () => {
console.log(arguments)
}
fn1(1,2,3);
// 4. 箭头函数的简写
// 1)省略小括号,当形参且只有一个的时候
let add = n => {
return n + n;
}
console.log(add(9))
// 2)省略花括号,当代码体只有一条语句的时候,此时 return 必须省略,而且语句的执行结果就是函数的返回值
let pow = (n) => n*n;
console.log(pow(8))
</script>
</body>
</html>
函数参数默认值设置
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>函数参数默认值设置</title>
</head>
<body>
<script>
// ES6 允许给函数参数赋值初始值
// 1. 形参初始值 具有默认值的参数,一般位置要靠后(潜规则)
function add(a,b,c=10) {
return a + b + c;
}
let result = add(1,2);
console.log(result);
// 2. 与解构赋值结合
function connect({host=`127.0.0.1`,username,password,port}){
console.log(host)
console.log(username)
console.log(password)
console.log(port)
}
connect({
host: `atguigu.com`,
username: `root`,
password: `root`,
port: 3306
})
</script>
</body>
</html>
rest参数 …args
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>rest参数</title>
</head>
<body>
<script>
// ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments
// ES5 获取实参的方式
function date(){
console.log(arguments);
}
date(`白芷`,`阿娇`,`思慧`);
// rest 参数
function dateRest(...args){
console.log(args);
}
dateRest(`白芷`,`阿娇`,`思慧`);
// rest参数必须要放到参数最后
function fn(a,b,...args){
console.log(a)
console.log(b)
console.log(args)
}
fn(1,2,3,4,5,6);
</script>
</body>
</html>
扩展运算符
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>扩展运算符</title>
</head>
<body>
<script>
// [...] 扩展运算符能将[数组]转换为逗号分隔的参数序列
// 声明一个数组 ...
const tfboys = ['易烊千玺','王源','王俊凯'];
// =>'易烊千玺','王源','王俊凯'
// 声明一个函数
function chunwan(){
console.log(arguments);
}
chunwan(...tfboys); // chunwan('易烊千玺',王源',王俊凯')
</script>
</body>
</html>
Symbol 独一无二的值
ES6 引入了一种新的原始数据类型Symbol
,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,是一种类似于字符串的数据类型。
Symbol
特点-
Symbol
的值是唯一的,用来解决命名冲突的问题
-
Symbol
值不能与其他数据进行运算
-
Symbol
定义的对象属性不能使用for...in
遍历,但是可以使用Reflect.ownKeys
来获取对象的所有键名
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>symbol</title>
</head>
<body>
<script>
// 创建Symbol
let s = Symbol();
// console.log(s, typeof s);
let s2 = Symbol('尚硅谷');
let s3 = Symbol('尚硅谷');
// Symbol.for 创建
let s4 = System.for('尚硅谷');
let s5 = Symbol.for('尚硅谷');
// 不能与其他数据进行运算
// let result = s + 100;
// let result = s > 100;
// let result = s + s;
// USONB you·are·so·niubility
// u undefined
// s string symbol
// o object
// n null number
// b boolean
</script>
</body>
</html>
生成器函数
生成器函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同。
生成器函数声明与调用
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>生成器函数</title>
</head>
<body>
<script>
// 生成器其实就是一个特殊的函数
// 异步编程 纯回调函数
// 函数代码的分隔符
function * gen(){
console.log(111);
yield '一只没有耳朵';
console.log(222);
yield '一直没有尾巴';
console.log(333);
yield '真奇怪';
console.log(444);
}
// 分布执行,并返回结果,调用next()则执行一步,yield就是执行完返回的结果
let iterator = gen();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
// 遍历
for(let v of gen()){
console.log(v);
}
</script>
</body>
</html>
生成器函数的参数传递
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>生成器函数参数传递</title>
</head>
<body>
<script>
function * gen(arg){
console.log(arg);
let one = yield 111;
console.log(one);
let two = yield 222;
console.log(two);
let three = yield 333;
console.log(three);
}
// 执行获取迭代器对象
let iterator = gen('AAA');
console.log(iterator.next());
// next方法可以传入实参,并且将会作为yield的返回结果
console.log(iterator.next('BBB'));
console.log(iterator.next('CCC'));
console.log(iterator.next('DDD'));
</script>
</body>
</html>
Promise 构造函数
Promise 是 ES6 引入的异步编程的新解决方案。语法上 Promise 是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。
- Promise 构造函数:
Promise(excutor){}
Promise.prototype.then
方法Promise.prototype.catch
方法
基本语法
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Promise基本语法</title>
</head>
<body>
<script>
// 实例化 Promise 对象
const p = new Promise(function(resolve,reject){
setTimeout(() => {
// let data = '数据库中的用户数据';
// resolve(data);
let err = '数据读取失败';
reject(err);
}, 1000);
})
// 调用 promise 对象的 then 方法
p.then(function(value){
console.log(value);
},function(reason){
console.error(reason);
});
</script>
</body>
</html>
Promise.prototype.then 方法
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Promise-then方法</title>
</head>
<body>
<script>
// 创建 Promise 对象
const p = new Promise((resolve,reject) => {
setTimeout(() => {
resolve('用户数据');
}, 1000);
})
// 调用 then 方法,then 方法的返回结果是 Promise 对象,对象状态由回调函数的执行结果决定。
// 1. 如果回调函数中返回的结果是 非 promise 类型的属性,状态为成功,返回值为对象的成功的值
// const result = p.then(value => {
// console.log(value)
// // 1. 非 promise 类型的属性
// // return 'iloveyou';
// // 2. 是 promise 对象
// // return new Promise((resolve,reject) => {
// // // resolve('ok');
// // reject('error')
// // })
// // 3. 抛出错误
// // throw new Error('出错了!');
// throw '出错了!';
// }, reeason => {
// console.warn(reeason);
// });
// console.log(result);
// 链式调用
p.then(value => {
}).then(value => {
})
</script>
</body>
</html>
Promise.prototype.catch 方法
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Promise-catch方法</title>
</head>
<body>
<script>
const p = new Promise((resolve,reject) => {
setTimeout(() => {
// 设置 p 对象的状态为失败,并设置失败的值
reject('出错了!');
}, 1000);
})
// p.then(function(value){},function(reason){
// console.error(reason)
// })
// catch是一个语法糖,可以在 then 方法的基础上省略第一个参数
p.catch(function(reason){
console.warn(reason)
})
</script>
</body>
</html>
class
class介绍与初体验
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>class介绍与初体验</title>
</head>
<body>
<script>
class Shouji {
// 构造方法,名字不能修改
constructor(brand,price){
this.brand = brand;
this.price = price;
}
// 方法必须使用该语法,不能使用ES5的对象完整形式
call(){
console.log('我可以打电话!')
}
}
let onePlus = new Shouji("1+",1999);
console.log(onePlus);
</script>
</body>
</html>
class类的静态成员
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>class类的静态成员</title>
</head>
<body>
<script>
class Phone {
// 静态属性
static name = '手机';
static change(){
console.log('我可以改变世界');
}
}
let nokia = new Phone();
console.log(nokia.name);
console.log(Phone.name);
</script>
</body>
</html>
class类继承
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>class类继承</title>
</head>
<body>
<script>
class Phone {
// 构造方法
constructor(brand,price){
this.brand = brand;
this.price = price;
}
// 父类的成员属性
call(){
console.log('我可以打电话!!')
}
}
class SmartPhone extends Phone {
// 构造方法
constructor(brand,price,color,size){
super(brand,price);
this.color = color;
this.size = size;
}
photo(){
console.log('拍照');
}
playGame(){
console.log('玩游戏');
}
}
const xiaomi = new SmartPhone('小米',799,'黑色','4.7inch');
console.log(xiaomi);
xiaomi.call();
xiaomi.photo();
xiaomi.playGame();
</script>
</body>
</html>
class的get和set
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>class的get和set</title>
</head>
<body>
<script>
class Phone {
get price(){
console.log('价格属性被读取了');
return 'iloveyou';
}
set price(newVal){
console.log('价格属性被修改了');
}
}
// 实例化对象
let s = new Phone();
console.log(s.price);
s.price = 'free';
</script>
</body>
</html>
数值扩展
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>数值扩展</title>
</head>
<body>
<script>
// Number.EPSILON 是 JavaScript 表示的最小精度
// EPSILON 属性的值接近于 2.2204460492503130808472633361816E-16
function equal(a,b){
if(Math.abs(a-b) < Number.EPSILON){
return true;
}else{
return false;
}
}
console.log('0.1 + 0.2 === 0.3 ',0.1 + 0.2 === 0.3)
console.log('equal(0.1 + 0.2,0.3) ',equal(0.1 + 0.2,0.3))
// Number.isFinite 检测一个数值是否为有限数
console.log('Number.isFinite(100) ',Number.isFinite(100));
console.log('Number.isFinite(100/0) ',Number.isFinite(100/0));
console.log('Number.isFinite(Infinity) ',Number.isFinite(Infinity));
// Number.isNaN 检测一个数值是否为 NaN
console.log('Number.isNaN(123) ',Number.isNaN(123));
// Number.parseInt Number.parseFloat字符串转整数
console.log(`Number.parseInt('521314love') `,Number.parseInt('521314love'))
console.log(`Number.parseFloat('3.1415926神奇') `,Number.parseFloat('3.1415926神奇'))
// Number.isInteger 判断一个数是否为整数
console.log('Number.isInteger(5) ',Number.isInteger(5));
console.log('Number.isInteger(2.5) ',Number.isInteger(2.5));
// Math.trunc 将数字的小数部分抹掉
console.log('Math.trunc(3.5) ',Math.trunc(3.5));
// Math.sign 判断一个数到底为正数 负数 还是零
console.log('Math.sign(100) ',Math.sign(100))
console.log('Math.sign(0) ',Math.sign(0))
console.log('Math.sign(-20000) ',Math.sign(-20000))
</script>
</body>
</html>
对象方法扩展
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>对象方法扩展</title>
</head>
<body>
<script>
// 1. Object.is 判断两个值是否完全相等
console.log(Object.is(120,120)); // true
console.log(Object.is(NaN,NaN)); // true
console.log(NaN === NaN); // false
// 2. Object.assign 对象的合并,如果对象中的属性存在则覆盖,不存在则合并
const config1 = {
host: 'localhost',
port: 3306,
name: 'root',
pass: 'root',
test: 'test'
};
const config2 = {
host: 'http://atguigu.com',
port: 33060,
name: 'atguigu.com',
pass: 'iloveyou',
test2: 'test2'
}
console.log(Object.assign(config1,config2));
// 3. Object.setPrototypeOf 设置原型对象 与 Object.getPrototypeOf 获取原型对象
const school = {
name: '尚硅谷'
}
const cities = {
xiaoqu: ['北京','上海','深圳']
}
Object.setPrototypeOf(school,cities);
console.log(Object.getPrototypeOf(school))
console.log(school)
</script>
</body>
</html>
模块化语法
模块功能主要由两个命令构成:export
和import
。
export
命令用于规定模块的对外接口。import
命令用于输入其他模块提供的功能。
m1.js
// 分别暴露
export let school = '尚硅谷';
export function teach() {
console.log('我们可以教给你开发技能')
}
m2.js
// 统一暴露
let school = '尚硅谷';
function findJob(){
console.log('我们可以帮你找工作');
}
export {school,findJob};
m3.js
// 默认暴露
export default {
school: 'ATGUIGU',
change: function(){
console.log('我们可以改变你!');
}
}
app.js
// 入口文件
// 1. 通用的导入方式
// 引入 m1.js 模块内容
import * as m1 from './m1.js';
console.log(m1);
// 引入 m2.js 模块内容
import * as m2 from './m2.js';
console.log(m2);
// 引入 m3.js 模块内容
import * as m3 from './m3.js';
console.log(m3);
m3.default.change();
// 2. 解构赋值形式
import {school, teach} from './m1.js';
console.log(school);
console.log(teach);
import {school as guigu, findJob} from './m2.js';
console.log(guigu);
console.log(findJob);
// 3. 简便形式 针对默认暴露
import defaultM3 from './m3.js';
console.log(defaultM3);
index.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>模块化</title>
</head>
<body>
<script src="./app.js" type="module"></script>
</body>
</html>