ES6新特性
数据类型
基本数据类型
string number boolean null undefined
复杂数据类型
Object Array Math Date String Number Boolean ...
symbol [基本数据类型]
ES6新增的基本数据类型 ,ES5的对象属性名都是字符串,很容易造成属性名冲突。
symbol表示独一无二的值,保证每个属性的名字都是独一无二的,这样就从根本上防止了属性名冲突。
定义
let sym = Symblo('描述符')
- 描述符:描述当前Symbol表示什么独一无二意义
- 若有两个描述符相同的Symbol 值也是不同的
function test2(){ let num = 100 let str = 'helloworld' let sname1 = Symbol('name') let sname2 = Symbol('name') console.log( typeof num) // number console.log( typeof str) // string console.log( typeof sname1) // symbol console.log(sname1 === sname2) //false } test2()
set [复杂数据类型]
存储无序数据的集合
创建
let set = new Set() //空集合
let set = new Set([1,2,{name:'jack'},function(){},'hello']) //可以是任何类型 key只能是字符串
属性和方法
<button class="add">添加</button>
<button class="delete">删除</button>
.size:用来获取该结构有多少个数据
.forEach():遍历集合Set
function test1(){
let set = new Set([10,20])
console.log(set) //10 20
console.log('size :',set.size) //2
set.forEach(function(item){
console.log(item) //10 20
})
.add():向该数据类型中追加数据
<button class="add">添加</button>
btnAdd.addEventListener('click',function(){
set.add(20)
console.log(set) //10 20
})
.delete():删除该数据中的某一个数据
.clear():清空数据
<button class="delete">删除</button>
btnDelete.addEventListener('click',function(){
set.delete(20) // 10
// set.clear() //清空
console.log(set)
})
将Set转为数组
function test3(){
// let arr = [10,20,10,30,20]
// console.log(arr)
// let set = new Set(arr)
// arr = [...set]
// console.log(arr)
// 代码行数越少出错概略越低
let arr = [10,20,10,30,20]
arr = [...new Set(arr)]
console.log(arr)
}
test3()
特点
集合set中元素不能重复
应用:数组去重
Map [复杂数据类型]
作用
是一个数据集合,是一个很类似于对象Object的数据集合
Map存储的数据是key/value 键值对形式,key可以是任意类型
创建
let map = new Map()
let map = new Map([ ['name'],[100,18] ])
属性和方法
.size :用来获取该数据类型中的个数
.delete() :用来删除集合中的某一个数据
.set() :用来向该数据集合中添加数据使用
.get(key) :用来获取该key的value
.clear() :清空数据
.has() :判断集合是否有数据
function test2() {
let map = new Map([
['name', 'jack'],
[100, 18],
])
console.log(map) //'name' => 'jack' 100 = >18
console.log(map.size) //2
//添加元素
map.set(true, '成立') //'name' => 'jack' 100 = >18 true => '成立'
console.log(map)
//获取元素
console.log(map.get('name')) //'jack'
//删除元素
map.delete('name')
console.log(map)
//判断集合是否有数据
let isHas = map.has('name') //true
console.log('isHas ', isHas)
}
test2()
特点
查找存储在map中的数据,可以不用遍历,根据key直接获取
value = map.get(key)
let arr = [
{ name: '钢筋', value: 11 },
{ name: '水泥', value: 12 },
{ name: '混泥土', value: 13 },
{ name: '加气砖', value: 14 },
]
let map = new Map()
arr.forEach(item=>{
map.set(item.value,item.name) // [11,'钢筋']
})
console.log(map.get(12))
for..of循环
用来遍历数组,字符串,Map;对象用for..in循环
语法
- for( let v of arr){} v是数组元素,也可以写成其他
let arr = [10, 20, 30, 40] for (const v of arr) { //v是数组元素 console.log(v) // 10 20 30 40 }
- for( let v of str){} v是字符
let str = 'hello' for (const v of str) { console.log(v) //hello }
- for( let v of map){}
let map = new Map([['hello','world'],[100,true]]) for (const v of map) { console.log(v); }
for...in[对象使用]
function test1() {
//遍历对象Object
// for-in
let obj = {
name: 'jack',
age: 18,
}
for (let key in obj) {
console.log(key, obj[key])
}
}
test1()
模块化语法import/export
每个js文件都可以看做一个模块 xx.js
每个js模块中的内容与其它模块相互独立
模块间通讯第一次方式
- a.js 暴露模块 export {变量或方法名} || 直接在函数前面加export
- b.js 引入模块 import {变量,方法} from './a.js'
- index.html <script type="module"> import {变量,方法} from './a.js' </script>
<h2>模块化编程</h2> <p>最大值是<span></span></p> <script type="module"> import { getMax } from './a.js' // 引入a.js模块中的getMax方法 import jackObj from './c.js' // jackObj可以随便换名字 let max = getMax(20, 34) // 显示最大值 const spanEle = document.querySelector('span') spanEle.innerHTML = max console.log('jackObj ',jackObj) </script>
import { getSum } from './b.js' //a.js let num = 100 //直接在需要暴露的方法前加export export const getMax = function(m,n){ let max = m if(n > max){ max = n } return max } let sum = getSum() console.log('sum ',sum)
export const getSum = function(){ //b.js let arr = [10,20,30] return arr.reduce((privous,current)=>privous = privous + current,0) }
模块间通讯第二方法
- export default {name:'jack'} //默认方式,只能有一个,不用写名字
- import A from 'c.js' //调用默认方式 A是名字,随便取什么都不会影响
export default { //c.js name:'jack', age:18 }
JS错误处理机制
javascript引擎负责执行javascript代码
如果发现错误代码,抛出异常错误, 如果异常错误没有处理语句,继续向上抛,至到系统处理
系统处理方式: 终止程序执行,在控制显示异常错误信息
异常错误类型
每个异常对应一个异常对象
- SyntaxError 语法错误
- ReferenceError 引用错误
- TypeError 类型错误
- RangeError 值超出有效范围时发生的错误
自己捕获异常进行处理
try{
// 可能发生异常的代码
}catch(error){
console.log(error)
}
购物车
<div class="containter">
<!--==== logo区域===== -->
<div class="logo">
<img src="./image/dd_logo.jpg" alt="logo" />
</div>
<!--==== 购物车列表区域==== -->
<table>
<!-- 动态渲染 -->
</table>
<!-- 所有商品总价 -->
<div>
<h2>总价:¥<span style="color: red;" class="total-price">0</span></h2>
</div>
<!-- 商品表单 -->
<div class="prowraper">
<form>
<input type="text" name="name" placeholder="请输入商品名"><br/>
<input type="text" name="price" placeholder="请输入商品价格"> <br/>
<input type="text" name="num" placeholder="请输入商品数量"> <br/>
<input type="text" name="url" placeholder="请输入商品图片地址"> <br/>
<input type="submit" id="confirm" value="添加商品">
</form>
</div>
</div>
<script src="./js/index.js"></script>
// 商品列表
let productList = [
{ number: 1001, name: 'javascript高级编程', url: './image/shoppingBg_03.jpg', price: 88.98, num: 0 },
{ number: 1002, name: 'css高级编程', url: './image/shoppingBg_06.jpg', price: 58.58, num: 0 },
{ number: 1003, name: 'html高级编程', url: './image/shoppingBg_03.jpg', price: 48.58, num: 0 },
]
const tableEle = document.querySelector('table')
const totalPriceEle = document.querySelector('.total-price')
/*
* 显示商品列表
*/
function showProductList() {
let str = `<tr>
<th>序列号</th>
<th>商品图片</th>
<th>商品信息</th>
<th>单价</th>
<th>数量</th>
<th width="100px">总价</th>
<th>操作</th>
</tr>`
let trArr = productList.map(item => {
return `<tr>
<td>${item.number}</td>
<td><img src="${item.url}" alt="图片1" /></td>
<td>${item.name}</td>
<td>¥${item.price}</td>
<td>
<input type="button" value="-" name="minus" ${item.num == 0 ? 'disabled' : ''} data-id="${
item.number
}"/><input type="text" value="${item.num}" name="amount"/><input
type="button"
value="+"
name="plus"
data-id="${item.number}"
/>
</td>
<td>¥${(item.price * item.num).toFixed(2)}</td>
<td>移入收藏<br /><a href="javascript:void(0)" class="del" data-id="${item.number}">删除</a></td>
</tr>`
})
str = str + trArr.join('')
tableEle.innerHTML = str
setTotalPrice() // 因为所有操作都会刷新商品列表,统一计算总价
}
/**
* 绑定添加商品事件
*/
function bindAddProduct() {
const formEle = document.querySelector('form')
const nameInput = document.querySelector('input[name="name"]')
const priceInput = document.querySelector('input[name="price"]')
const numInput = document.querySelector('input[name="num"]')
const urlInput = document.querySelector('input[name="url"]')
formEle.addEventListener('submit', function (e) {
e = e || window.event
e.preventDefault() // 阻止默认行为
let name = nameInput.value // 商品名称
let price = priceInput.value // 商品价格
let num = numInput.value // 商品数量
let url = urlInput.value // 商品地址
addProduct(name, price, num, url)
// 清空表单数据
nameInput.value = ''
priceInput.value = ''
numInput.value = ''
urlInput.value = ''
})
}
/**
* 添加商品
* 1. 构造商品对象
* let product = { number: 1004, name: 'vue高级编程', url: './image/shoppingBg_03.jpg', price: 108.58, num: 0 }
* 2. 添加商品到商品数组
* productList.push(product)
*/
function addProduct(name, price, num, url) {
let number = getRandom(1000, 10000) // 随机生成4位商品序号
// 1. 构造商品对象
let product = {
number,
name,
url,
price,
num,
}
productList.push(product) // 2. 添加商品到商品数组
showProductList() // 3. 重新加载商品数组
}
/*
* 返回m到n之间的随机数
*/
function getRandom(x, y) {
var n = Math.max(x, y)
var m = Math.min(x, y)
return Math.floor(Math.random() * (n - m) + m)
}
/**
* 绑定删除按钮事件
* 实现方式
* 事件属性
* 事件赋值
* 事件监听
* 事件委托- 动态添加的节点不需要重新绑定事件
*/
function bindDeleteProduct() {
// const delEles = document.querySelectorAll('.del')
// for(let i = 0; i < delEles.length; i++){
// delEles[i].addEventListener('click',function(){
// alert(i)
// })
// }
tableEle.addEventListener('click', function (e) {
e = e || window.event
let target = e.target || e.srcElement //事件目标对象
// 判断是否删除操作
if (target.getAttribute('class') == 'del') {
let id = target.dataset.id
// let index = getIndexByNumber(id)
// 遍历数组查询数组中满足条件的元素的索引号
let index = productList.findIndex(item => item.number == id)
productList.splice(index, 1)
// 重新刷新商品列表
showProductList()
}
// 加操作
if (target.getAttribute('name') == 'plus') {
let id = target.dataset.id
let product = productList.find(item => item.number == id)
product.num++ //数量加一
showProductList()
}
// 减操作
if (target.getAttribute('name') == 'minus') {
let id = target.dataset.id
let product = productList.find(item => item.number == id)
product.num-- //数量减一
// if(product.num <= 0){
// product.num =0
// }
showProductList()
}
})
}
/**
* 计算所有商品总价
*/
function getTotal() {
// let s = 0 //总价
// for(let i = 0; i < productList.length; i++){
// let product = productList[i]
// let singlePrice = product.price * product.num // 单个商品总价
// s += singlePrice
// }
let s = productList.reduce((previous, current) => (previous = previous + current.price * current.num), 0)
// productList.reduce(function(previous,current){
// return previous + current.price*current.num
// },0)
return s.toFixed(2)
}
/**
* 设置总价
*/
function setTotalPrice() {
let totalPrice = getTotal()
totalPriceEle.innerHTML = totalPrice
}
showProductList()
bindAddProduct()
bindDeleteProduct()
setTotalPrice()
/**
* 根据id查询索引号
* 如果没有返回-1
* @param {*} id
* @returns
*/
function getIndexByNumber(id) {
let _index = -1
productList.forEach((item, index) => {
if (item.number == id) {
_index = index
}
})
return _index
}
* {
padding: 0;
margin: 0;
}
a{
text-decoration: none;
color: rgb(43, 42, 42);
}
.containter {
width: 1200px;
margin: 100px auto;
}
.containter table{
width: 100%;
}
.containter tr {
line-height: 40px;
text-align: center;
}
.containter tr,
th,
td {
border-bottom: 1px dotted gray;
}
.containter tr input {
width: 20px;
text-align: center;
}
.containter h2{
font-size: 18px;
text-align: right;
}
.containter table img{
width: 80px;
height: 100px;
}
/* 添加商品表单 */
.prowraper{
width: 600px;
margin: 20px auto;
border: 1px solid gray;
}
.prowraper form{
width: 100%;
padding: 20px;
}
.prowraper form input{
margin-top: 10px;
width: 90%;
line-height: 30px;
}
.prowraper form #confirm{
margin-top: 10px;
width: 200px;
height: 40px;
text-align: center;
line-height: 40px;
}