一,es简介
1.什么是es?
ES全称是ECMAScript,它是由ECMA国际标准化组织通过ECMA-162标准
制定的一项脚本语言的标准化规范
ES2015 发布于201506
ES2016 发布于201606
ES2017 发布于201706
ES2018 发布于201806
es6是一次标志性的版本
ES6实际上是一个泛指,泛指ES2015及后续的版本
2.es6的作用是什么?
每一次标准的诞生都意味着语言的完整、功能的强大,JavaScript语言本身也有许多令人不满的地方
比如:变量提升
语法松散,实现相同的功能,不同的人写出不同的代码
语法更加简洁,原本几行的代码现在可能只需要一行
二,es6语法
1.let与const
let
let声明的变量只处在的块级有效,具有块级作用,可以向下
域(if\for\function)中
没有变量提升
console.log(a);//报错:a is not defined 如果是var声明的,会输出
let a = 1;
练习
var arr = [];
for(let i = 0;i < 3;i++){
arr[i] = function(){
console.log(i);
}
}
/* 每次循环都会产生一个块级作用域,每个块级作用域都对
应一个值,函数对应那个作用域的值。 */
arr[0]();//0
arr[1]();//1
const
const声明常量,常量就是值(内存地址)不能变化的量,也就是const锁定了内存地址的引用关系
//声明常量
const SCHOOL = '尚硅谷';
//1. 一定要赋初始值
const A;
//2. 一般常量使用大写(潜规则)
const a = 100;
// 3. 常量的值不能修改
SCHOOL = 'ATGUIGU';
//4. 块儿级作用域
{
const PLAYER = 'UZI';
}
console.log(PLAYER);//报错:a is not defined
//5. 对于数组和对象的元素修改, 不算做对常量的修改, 不会报错
const TEAM = ['UZI','MXLG','Ming','Letme'];
// TEAM.push('Meiko'); //修改的是引用地址,原数据没有发生变化
2.结构赋值
es6中允许从数组、对象中提取值,按照对应位置,进行赋值。
数组解构
let [a, b, c] = [1, 2, 3];
console.log(a); //1
console.log(b); //2
console.log(c); //3
// 没有对应值就是underfined
let [d, e, f] = [4];
console.log(d); //4
console.log(e); //undefined
console.log(f); //undefined
对象解构
// 对象解构:
let obj = { name: "刘德华", age: 18 };
// 变量名对应属性名,变量值对应属性值
let { name, age, sex } = obj;
console.log(name, age); // 刘德华,18
console.log(sex); // 没有对应值就是underfined
//别名
let { name: newName, age: newAge } = obj;
console.log(newName, newAge); //刘德华,18
//2. 对象的解构
const zhao = {
name: '赵本山',
age: '不详',
xiaopin: function(){
console.log("我可以演小品");
}
};
// let {name, age, xiaopin} = zhao;
// console.log(name);
// console.log(age);
// console.log(xiaopin);
// xiaopin();
let {xiaopin} = zhao;
xiaopin();//执行函数
3.模板字符串
// ES6 引入新的声明字符串的方式 『``』 '' ""
//1. 声明
let str = `我也是一个字符串哦!`;
console.log(str, typeof str);
内容中可以直接出现换行符,如果是单引号或双引号 换行需要用加号拼接
//2. 内容中可以直接出现换行符
let str = `<ul>
<li>沈腾</li>
<li>玛丽</li>
<li>魏翔</li>
<li>艾伦</li>
</ul>`;
//3. 变量拼接
let lovest = '魏翔';
let out = `${lovest}是我心目中最搞笑的演员!!`;
console.log(out);
4.对象简写
//ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。
//这样的书写更加简洁
let name = '尚硅谷';
let change = function(){
console.log('我们可以改变你!!');
}
const school = {
name,//等效于name:name
change,
improve(){//省略掉function关键字
console.log("我们可以提高你的技能");
}
}
console.log(school);
5.箭头函数
// ES6 允许使用「箭头」(=>)定义函数。
//声明一个函数
let fn = function(){
}
let fn = (a,b) => {
return a + b;
}
//调用函数
let result = fn(1, 2);
console.log(result);
this 是静态的. this 始终指向函数声明时所在作用域下的 this 的值
//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);//ATGUIGU
getName2.call(school);//尚硅谷
//2. 不能作为构造实例化对象
let Person = (name, age) => {
this.name = name;
this.age = age;
}
let me = new Person('xiao',30);
console.log(me);//报错,person不是构造器
//3. 不能使用 arguments 变量
let fn = () => {
console.log(arguments);
}
fn(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));
实践案例
<title>箭头函数实践</title>
<style>
div {
width: 200px;
height: 200px;
background: #58a;
}
</style>
</head>
<body>
<div id="ad"></div>
<script>
//需求-1 点击 div 2s 后颜色变成『粉色』
//获取元素
let ad = document.getElementById('ad');
//绑定事件
ad.addEventListener("click", function(){
//保存 this 的值
// let _this = this;
//定时器
setTimeout(() => {
//修改背景颜色 this
// console.log(this);//指向Window
// _this.style.background = 'pink';
this.style.background = 'pink';
}, 2000);
});
//需求-2 从数组中返回偶数的元素
const arr = [1,6,9,10,100,25];
const result = arr.filter(function(item){
if(item % 2 === 0){
return true;
}else{
return false;
}
});
const result2 = arr.filter(item => item % 2 === 0);
console.log(result);
// 箭头函数适合与 this 无关的回调. 定时器, 数组的方法回调
// 箭头函数不适合与 this 有关的回调. 事件回调, 对象的方法
</script>
6.参数默认值
很多语言都支持设置函数形参的默认值(java不支持,可以通过重载实现)
<script>
//ES6 允许给函数参数赋值初始值
//1. 形参初始值 具有默认值的参数, 一般位置要靠后(潜规则)
function add(a,c=10,b) {
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>
7.rest参数
// ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments
// ES5 获取实参的方式
function date(){
console.log(arguments);
}
date('白芷','阿娇','思慧');
// rest 参数
function date(...args){
console.log(args);// filter some every map
}
date('阿娇','柏芝','思慧');
// rest 参数必须要放到参数最后
function fn(a,b,...args){
console.log(a);
console.log(b);
console.log(args);
}
fn(1,2,3,4,5,6);
8.扩展运算符应用
//1. 数组的合并 情圣 误杀 唐探
const kuaizi = ['王太利','肖央'];
const fenghuang = ['曾毅','玲花'];
// const zuixuanxiaopingguo = kuaizi.concat(fenghuang);//传统方式
const zuixuanxiaopingguo = [...kuaizi, ...fenghuang];
console.log(zuixuanxiaopingguo);//合并后的数组
//2. 数组的克隆
const sanzhihua = ['E','G','M'];
const sanyecao = [...sanzhihua];// ['E','G','M'] 浅拷贝
console.log(sanyecao);
//3. 将伪数组转为真正的数组
const divs = document.querySelectorAll('div');
const divArr = [...divs];
console.log(divArr);// arguments
9.symbol
ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。它是
JavaScript 语言的第七种数据类型,是一种类似于字符串的数据类型。
// 第一种创建symbol的方式
let s = Symbol();
console.log(s, typeof s); // Symbol() symbol
// 传递一个字符串标识名,实际上s1和s2还是随机的,唯一的
let s1 = Symbol('zhangsan');
let s2 = Symbol('zhangsan');
console.log(s1 === s2); // false
// 第二种symbol.for创建,可以通过后面的标识符查询到,可以与后面的标识符一一对应
let s3 = Symbol.for('zhangsan');
let s4 = Symbol.for('zhangsan');
console.log(s3 === s4); // true
获取symbol的描述信息
let s = Symbol('zhangsan');
console.log(s.description); // zhangsan
注意事项
不能与其它数据类型进行运算
let s5 = Symbol.for('1');
s5 = s5 + 1;// Cannot convert a Symbol value to a number
值是唯一的?分情况!
let s1 = Symbol('zhangsan');
let s2 = Symbol('zhangsan');
let s3 = Symbol.for('zhangsan');
let s4 = Symbol.for('zhangsan');
/* 和 Symbol() 不同的是,用 Symbol.for() 方法创建的的
symbol 会被放入一个全局 symbol 注册表中。Symbol.for()
并不是每次都会创建一个新的 symbol,它会首先检查给定的
key 是否已经在注册表中了。假如是,则会直接返回上次存储
的那个。否则,它会再新建一个。 */
console.log(s1 === s2); // false
console.log(s3 === s4); // true
不能用for-in遍历
let obj = {};
obj[Symbol("1")] = 1;
obj[Symbol("2")] = 2;
for (const key in obj) {
if (Object.hasOwnProperty.call(obj, key)) {
console.log(key); // 无输出,遍历不到
const element = obj[key];
console.log(element); // 无输出,遍历不到
}
}
可以使用Reflect.ownKeys来获取定义的对象的所有键名,从而来遍历对象
let obj = {};
obj[Symbol("1")] = 1;
obj[Symbol("2")] = 2;
obj.a = 3;
const result = Reflect.ownKeys(obj);
console.log(result); // [ 'a', Symbol(1), Symbol(2) ]
for (const index of result) {
console.log(obj[index]); // 3 1 2
}
应用场景
// 当我们需要向一个对象中添加方法时,如果我们不知道对象内部是怎么样的,如果直接添加可能会有命名冲突
let obj = {
up() {
console.log("xiangshang");
},
down() {
console.log("xiangxia");
},
};
let symobj = {
up: Symbol(),
down: Symbol(),
};
obj[symobj.up] = function() {
console.log("我是新添加的up方法");
};
obj[symobj.down] = function() {
console.log("我是新添加的down方法");
};
console.log(obj);
/* {
up: [Function: up],
down: [Function: down],
[Symbol()]: [Function (anonymous)],
[Symbol()]: [Function (anonymous)]
} */
obj[symobj.down](); // 我是新添加的down方法
js中七种数据类型
USONB you are so niubility
u undefined
s string symbol
o object
n null number
b boolean
symbol内置属性
除了定义自己使用的 Symbol 值以外,ES6 还提供了 11 个内置的 Symbol 值,
指向语言内部使用的方法。可以称这些方法为魔术方法,因为它们会在特定的场
景下自动执行。
<script>
class Person{
static [Symbol.hasInstance](param){//hasInstance : 定义类型检测
console.log(param);
console.log("我被用来检测类型了");
return false;
}
}
let o = {};
console.log(o instanceof Person);
const arr = [1,2,3];
const arr2 = [4,5,6];
arr2[Symbol.isConcatSpreadable] = false;//isConcatSpreadable :控制数组值是否展开
console.log(arr.concat(arr2));
10.迭代器
- ES6 创造了一种新的遍历命令 for…of 循环,Iterator 接口主要供 for…of 消费
- 原生具备 iterator 接口的数据(可用 for of 遍历)
a) Array
b) Arguments
c) Set
d) Map
e) String
f) TypedArray
g) NodeList - 工作原理
a) 创建一个指针对象,指向当前数据结构的起始位置
b) 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员
c) 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员
d) 每调用 next 方法返回一个包含 value 和 done 属性的对象
注: 需要自定义遍历数据的时候,要想到迭代器。
//声明一个数组
const xiyou = ['唐僧','孙悟空','猪八戒','沙僧'];
//使用 for...of 遍历数组
for(let v of xiyou){
console.log(v);
}
let iterator = xiyou[Symbol.iterator]();
//调用对象的next方法
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
自定义迭代器
//声明一个对象
const banji = {
name: "终极一班",
stus: [
'xiaoming',
'xiaoning',
'xiaotian',
'knight'
],
//定义iterator函数
[Symbol.iterator]() {
//索引变量
let index = 0;
let _this = this;
return {
// 定义next 方法及返回值
next: function () {
if (index < _this.stus.length) {
console.log(this);
// 此处this指向当前对象 return的对象:next: ƒ ()
const result = { value: _this.stus[index], done: false };
//下标自增
index++;
//返回结果
return result;
}else{
return {value: undefined, done: true};
}
}
};
}
}
//遍历这个对象
for (let v of banji) {
console.log(v);
}
11.生成器
生成器函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同
//生成器其实就是一个特殊的函数
//异步编程 纯回调函数 node fs ajax mongodb
//函数代码的分隔符 将代码分块
function * gen(){
console.log(111);
yield '一只没有耳朵';
console.log(222);
yield '一只没有尾部';
console.log(333);
yield '真奇怪';
console.log(444);
}
// 生成器函数每次调用的时候都会生成一个新的支持迭代器的对象
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);
}
-
- 的位置没有限制
- 生成器函数返回的结果是迭代器对象,调用迭代器对象的 next 方法可以得到
yield 语句后的值 - yield 相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次 next
方法,执行一段代码 - next 方法可以传递实参,作为 yield 语句的返回值
//给生成器函数异步传参
function * gen(arg){
console.log(arg);
// 可以使用一个变量去接收yield的返回值,yield返回上一次调用iterator.next()的参数
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方法可以传入实参
console.log(iterator.next('BBB'));
console.log(iterator.next('CCC'));
console.log(iterator.next('DDD'));
实例:回调地狱
// 异步编程 文件操作 网络操作(ajax, request) 数据库操作
// 1s 后控制台输出 111 2s后输出 222 3s后输出 333
// 回调地狱 不停的回调,一层套一层
// setTimeout(() => {
// console.log(111);
// setTimeout(() => {
// console.log(222);
// setTimeout(() => {
// console.log(333);
// }, 3000);
// }, 2000);
// }, 1000);
function one(){
setTimeout(()=>{
console.log(111);
iterator.next();
},1000)
}
function two(){
setTimeout(()=>{
console.log(222);
iterator.next();
},2000)
}
function three(){
setTimeout(()=>{
console.log(333);
iterator.next();
},3000)
}
function * gen(){
yield one();
yield two();
yield three();
}
//调用生成器函数
let iterator = gen();
iterator.next();
模拟场景
//模拟获取 用户数据 订单数据 商品数据
function getUsers(){
setTimeout(()=>{
let data = '用户数据';
//调用 next 方法, 并且将数据传入
iterator.next(data);
}, 1000);
}
function getOrders(){
setTimeout(()=>{
let data = '订单数据';
iterator.next(data);
}, 1000)
}
function getGoods(){
setTimeout(()=>{
let data = '商品数据';
iterator.next(data);
}, 1000)
}
function * gen(){
let users = yield getUsers();
let orders = yield getOrders();
let goods = yield getGoods();
}
//调用生成器函数
let iterator = gen();
iterator.next();
12.promise
Promise 是 ES6 引入的异步编程的新解决方案。语法上 Promise 是一个构造函数,
用来封装异步操作并可以获取其成功或失败的结果。
- Promise 构造函数: Promise (excutor) {}
- Promise.prototype.then 方法
- Promise.prototype.catch 方法
基本语法
//实例化 Promise 对象 三种状态:初始化/成功/失败
const p = new Promise(function(resolve, reject){
setTimeout(function(){
//
// let data = '数据库中的用户数据';
// resolve //标识成功状态,调用第一个回调函数
// resolve(data);
let err = '数据读取失败';
reject(err);//标识失败状态,调用第二个回调函数
}, 1000);
});
//调用 promise 对象的 then 方法
p.then(function(value){
console.log(value);
}, function(reason){
console.error(reason);
})
promise封装读取文件
//1. 引入 fs 模块
const fs = require('fs');
//2. 调用方法读取文件
// fs.readFile('./resources/为学.md', (err, data)=>{
// //如果失败, 则抛出错误
// if(err) throw err;
// //如果没有出错, 则输出内容
// console.log(data.toString());
// });
//3. 使用 Promise 封装
const p = new Promise(function(resolve, reject){
fs.readFile("./resources/为学.mda", (err, data)=>{
//判断如果失败
if(err) reject(err);
//如果成功
resolve(data);
});
});
p.then(function(value){
console.log(value.toString());
}, function(reason){
console.log("读取失败!!");
});
promise封装AJAX
// 接口地址: https://api.apiopen.top/getJoke
const p = new Promise((resolve, reject) => {
//1. 创建对象
const xhr = new XMLHttpRequest();
//2. 初始化
xhr.open("GET", "https://api.apiopen.top/getJoke");
//3. 发送
xhr.send();
//4. 绑定事件, 处理响应结果
xhr.onreadystatechange = function () {
//判断
if (xhr.readyState === 4) {
//判断响应状态码 200-299
if (xhr.status >= 200 && xhr.status < 300) {
//表示成功
resolve(xhr.response);
} else {
//如果失败
reject(xhr.status);
}
}
}
})
//指定回调
p.then(function(value){
console.log(value);
}, function(reason){
console.error(reason);
});
then方法
指定回调函数
//创建 promise 对象
const p = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('用户数据');
// reject('出错啦');
}, 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 '出错啦!';
}, reason=>{
console.warn(reason);
});
//链式调用
p.then(value=>{
}).then(value=>{
});
then方法多次回调将多个异步方法串联起来
//引入 fs 模块
const fs = require("fs");
// fs.readFile('./resources/为学.md', (err, data1)=>{
// fs.readFile('./resources/插秧诗.md', (err, data2)=>{
// fs.readFile('./resources/观书有感.md', (err, data3)=>{
// let result = data1 + '\r\n' +data2 +'\r\n'+ data3;
// console.log(result);
// });
// });
// });
//使用 promise 实现
const p = new Promise((resolve, reject) => {
fs.readFile("./resources/为学.md", (err, data) => {
resolve(data);
});
});
p.then(value => {
return new Promise((resolve, reject) => {
fs.readFile("./resources/插秧诗.md", (err, data) => {
resolve([value, data]);
});
});
}).then(value => {
return new Promise((resolve, reject) => {
fs.readFile("./resources/观书有感.md", (err, data) => {
//压入
value.push(data);
resolve(value);
});
})
}).then(value => {
console.log(value.join('\r\n'));
});
catch方法:指定失败后的回调
<script>
const p = new Promise((resolve, reject)=>{
setTimeout(()=>{
//设置 p 对象的状态为失败, 并设置失败的值
reject("出错啦!");
}, 1000)
});
// p.then(function(value){}, function(reason){
// console.error(reason);
// });
p.catch(function(reason){
console.warn(reason);
});
</script>
13.set
ES6 提供了新的数据结构 Set(集合)。它类似于数组,但成员的值都是唯
一的,集合实现了 iterator 接口,所以可以使用『扩展运算符』和『for…of…』进
行遍历,集合的属性和方法:
- size 返回集合的元素个数
- add 增加一个新元素,返回当前集合
- delete 删除元素,返回 boolean 值
- has 检测集合中是否包含某个元素,返回 boolean 值
- clear 清空集合,返回 undefined
//声明一个 set
let s = new Set();
let s2 = new Set(['大事儿','小事儿','好事儿','坏事儿','小事儿']);
//元素个数
console.log(s2.size);
//添加新的元素
s2.add('喜事儿');
//删除元素
s2.delete('坏事儿');
//检测是否包含
console.log(s2.has('糟心事'));
//清空
s2.clear();
console.log(s2);
for(let v of s2){
console.log(v);
}
实践:去重,取交集/差集/并集
let arr = [1,2,3,4,5,4,3,2,1];
//1. 数组去重
let result = [...new Set(arr)];
console.log(result);
//2. 交集
let arr2 = [4,5,6,5,6];
let result = [...new Set(arr)].filter(item => {
let s2 = new Set(arr2);// 4 5 6
if(s2.has(item)){
return true;
}else{
return false;
}
});
// 简写
// let result = [...new Set(arr)].filter(item => new Set(arr2).has(item));
console.log(result);
//3. 并集 (直接合并)
let union = [...new Set([...arr, ...arr2])];
console.log(union);
//4. 差集
let diff = [...new Set(arr)].filter(item => !(new Set(arr2).has(item)));
console.log(diff);
14.map
ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合。但是“键”
的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map 也实现了
iterator 接口,所以可以使用『扩展运算符』和『for…of…』进行遍历。Map 的属
性和方法:
- size 返回 Map 的元素个数
- set 增加一个新元素,返回当前 Map
- get 返回键名对象的键值
- has 检测 Map 中是否包含某个元素,返回 boolean 值
- clear 清空集合,返回 undefined
//声明 Map
let m = new Map();
//添加元素
m.set('name','尚硅谷');
// 值设置的是个函数
m.set('change', function(){
console.log("我们可以改变你!!");
});
let key = {
school : 'ATGUIGU'
};
//键设置的是对象
m.set(key, ['北京','上海','深圳']);
//size
console.log(m.size);
//删除
m.delete('name');
//获取
console.log(m.get('change'));
console.log(m.get(key));
//清空
// m.clear();
//遍历
for(let v of m){
console.log(v);
}
// console.log(m);
15.class类
ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对
象的模板。通过 class 关键字,可以定义类。基本上,ES6 的 class 可以看作只是
一个语法糖,它的绝大部分功能,ES5 都可以做到,新的 class 写法只是让对象
原型的写法更加清晰、更像面向对象编程的语法而已。
知识点:
- class 声明类
- constructor 定义构造函数初始化
- extends 继承父类
- super 调用父级构造方法
- static 定义静态方法和属
声明
// es5构造函数写法
//手机
function Phone(brand, price){
this.brand = brand;
this.price = price;
}
//添加方法
Phone.prototype.call = function(){
console.log("我可以打电话!!");
}
//实例化对象
let Huawei = new Phone('华为', 5999);
Huawei.call();
console.log(Huawei);
//class写法
class Shouji{
//构造方法 名字不能修改
constructor(brand, price){
this.brand = brand;
this.price = price;
}
//方法必须使用该语法, 不能使用 ES5 的对象完整形式
call(){
console.log("我可以打电话!!");
}
}
let onePlus = new Shouji("1+", 1999);
console.log(onePlus);
静态成员
类似于Java中通过类名调用静态属性
function Phone(){
}
// 属于类的,而不是属于实例对象的
Phone.name = '手机';
Phone.change = function(){
console.log("我可以改变世界");
}
Phone.prototype.size = '5.5inch';
let nokia = new Phone();
console.log(nokia.name);
// nokia.change();
console.log(nokia.size);
class Phone{
//静态属性
static name = '手机';
static change(){
console.log("我可以改变世界");
}
}
let nokia = new Phone();
console.log(nokia.name);//undefinde
console.log(Phone.name);//手机
继承
es5构造函数继承
//手机
function Phone(brand, price){
this.brand = brand;
this.price = price;
}
Phone.prototype.call = function(){
console.log("我可以打电话");
}
//智能手机
function SmartPhone(brand, price, color, size){
Phone.call(this, brand, price);
this.color = color;
this.size = size;
}
//设置子级构造函数的原型
SmartPhone.prototype = new Phone;
SmartPhone.prototype.constructor = SmartPhone;
//声明子类的方法
SmartPhone.prototype.photo = function(){
console.log("我可以拍照")
}
SmartPhone.prototype.playGame = function(){
console.log("我可以玩游戏");
}
const chuizi = new SmartPhone('锤子',2499,'黑色','5.5inch');
console.log(chuizi);
es6类继承
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);// Phone.call(this, brand, price)
this.color = color;
this.size = size;
}
photo(){
console.log("拍照");
}
playGame(){
console.log("玩游戏");
}
call(){
console.log('我可以进行视频通话');
}
}
const xiaomi = new SmartPhone('小米',799,'黑色','4.7inch');
// console.log(xiaomi);
xiaomi.call();
xiaomi.photo();
xiaomi.playGame();
get和set
class Phone{
get price(){
console.log("价格属性被读取了");
return 'iloveyou';
}
set price(newVal){//声明时必须要有形参
console.log('价格属性被修改了');
}
}
//实例化对象
let s = new Phone();
// console.log(s.price);
s.price = 'free';
16.数值扩展
//0. 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);//false
console.log(equal(0.1 + 0.2, 0.3))//true
//1. 二进制和八进制
let b = 0b1010;//0b开头
let o = 0o777;//0o开头
let d = 100;
let x = 0xff;
// console.log(x);
//2. Number.isFinite 检测一个数值是否为有限数
console.log(Number.isFinite(100));
console.log(Number.isFinite(100/0));
console.log(Number.isFinite(Infinity));
//3. Number.isNaN 检测一个数值是否为 NaN
console.log(Number.isNaN(123));
//4. Number.parseInt Number.parseFloat字符串转整数
console.log(Number.parseInt('5211314love'));
console.log(Number.parseFloat('3.1415926神奇'));
//5. Number.isInteger 判断一个数是否为整数
console.log(Number.isInteger(5));
console.log(Number.isInteger(2.5));
//6. Math.trunc 将数字的小数部分抹掉
console.log(Math.trunc(3.5));
//7. Math.sign 判断一个数到底为正数 负数 还是零
console.log(Math.sign(100));
console.log(Math.sign(0));
console.log(Math.sign(-20000));
17.方法扩展
ES6 新增了一些 Object 对象的方法
- Object.is 比较两个值是否严格相等,与『===』行为基本一致(+0 与 NaN)
- Object.assign 对象的合并,将源对象的所有可枚举属性,复制到目标对象
- proto、setPrototypeOf、 setPrototypeOf 可以直接设置对象的原型
//1. Object.is 判断两个值是否完全相等
console.log(Object.is(120, 120));// ===
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);
三.模块化
模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。
标题模块化的好处
模块化的优势有以下几点:
- 防止命名冲突
- 代码复用
- 高维护性
标题模块化规范产品
ES6 之前的模块化规范有:
- CommonJS => NodeJS、Browserify
- AMD => requireJS
- CMD => seaJS
标题ES6 模块化语法
模块功能主要由两个命令构成:export 和 import。
⚫ export 命令用于规定模块的对外接口
⚫ import 命令用于输入其他模块提供的功能
基本方式
js文件
export var a = 1;
export function b() {
console.log("b");
}
html
<script type="module">
// 将文件中所有的导出都放在obj对象里面
import * as obj from "./index.js";
console.log(obj);
</script>
方式汇总
js
let name = 'xiaoming';
let flag = true;
function sum(num1,num2){
return num1+num2
}
let b = 1;
let c = 2;
if(flag){
console.log(sum(10,20));
}
// 单独暴露
// 导出方式1
export {
flag,sum
}
// 导出方式2
export let a = 1;
// 导出函数
export function fn2(){
console.log('我是函数2');
}
// 导出类
export class Person {
constructor(name,age) {
this.name = name;
this.age = age;
}
// 行走
run(){
console.log(this.name + '在走路');
}
}
// default导出的方式,可以让引入者自己命名,只能有一个default,要想导出多个变量,可以使用对象的形式
const abc = 'abc';
export default abc
// 解构赋值引入需要的变量
import {
flag as flags,
sum,
a,
fn2,
Person
} from './a.js';
// 引入默认暴露
import defaultabc from './a.js';
import $ from 'jquery';
// 导入所有的变量,as用来起别名,在前面的对象中也可以使用
import * as obj from './a.js';
if (flags) {
console.log(sum(20, 20));
console.log(a);
fn2();
new Person('刘德华', 18).run();
console.log(defaultabc);
obj.fn2();
}
$('body').css('background-color', 'pink');
导出的方式:
1、export 变量会默认添加到导出的整个对象中,成为对象的属性
2、export {变量1,变量2}会默认被解析成变量序列并添加到导出的整个对象中,成为对象的属性
3、export default 默认导出,将会被默认导入接收到
导入的方式:
1、import {变量1 as 重命名,变量2}对象解构去匹配导出的整个对象中的相同的变量名,没有匹配到为undefined,可以重命名
2、import 变量,默认导入,可以接收到默认导出
3、import * as 变量名,全部导入,可以接收到文件中的所有导出,包括默认导出。
js入口文件引入模块
js文件
//入口文件
//模块引入
import * as m1 from "./m1.js";
import * as m2 from "./m2.js";
import * as m3 from "./m3.js";
引用入口文件
<script src="./src/js/app.js" type="module"></script>