四. ES6
- 我们所说的 ES5 和 ES6 其实就是在 js 语法的发展过程中的一个版本而已
- ECMAScript 就是 js 的语法
- 以前的版本没有某些功能
- 在 ES5 这个版本的时候增加了一些功能
- 在 ES6 这个版本的时候增加了一些功能
- 因为浏览器是浏览器厂商生产的
- ECMAScript 发布了新的功能以后,浏览器厂商需要让自己的浏览器支持这些功能
- 这个过程是需要时间的
- 所以到现在,基本上大部分浏览器都可以比较完善的支持了
- 只不过有些浏览器还是不能全部支持
- 这就出现了兼容性问题
- 所以我们写代码的时候就要考虑哪些方法是 ES5 或者 ES6 的,看看是不是浏览器都支持
1.ES6定义变量
let 和 const 关键字
1.let变量
2.const常量
-
我们以前都是使用
var关键字来声明变量的 -
在 ES6 的时候,多了两个关键字
let和const,也是用来声明变量的 -
只不过和 var 有一些区别
let 和 const 的相同点
1. let 和 const 不允许重复声明变量
```javascript
// 使用 var 的时候重复声明变量是没问题的,只不过就是后面会把前面覆盖掉
var num = 100
var num = 200
```
```javascript
// 使用 let 重复声明变量的时候就会报错了
let num = 100
let num = 200 // 这里就会报错了
```
```javascript
// 使用 const 重复声明变量的时候就会报错
const num = 100
const num = 200 // 这里就会报错了
```
2. let 和 const 声明的变量不会在预解析的时候解析(也就是没有变量提升)
```javascript
// 因为预解析(变量提升)的原因,在前面是有这个变量的,只不过没有赋值
console.log(num) // undefined
var num = 100
```
```javascript
// 因为 let 不会进行预解析(变量提升),所以直接报错了
console.log(num) // undefined
let num = 100
```
```javascript
// 因为 const 不会进行预解析(变量提升),所以直接报错了
console.log(num) // undefined
const num = 100
```
3. let 和 const 声明的变量会被所有代码块限制作用范围
```javascript
// var 声明的变量只有函数能限制其作用域,其他的不能限制
if (true) {
var num = 100
}
console.log(num) // 100
```
```javascript
// let 声明的变量,除了函数可以限制,所有的代码块都可以限制其作用域(if/while/for/...)
if (true) {
let num = 100
console.log(num) // 100
}
console.log(num) // 报错
```
```javascript
// const 声明的变量,除了函数可以限制,所有的代码块都可以限制其作用域(if/while/for/...)
if (true) {
const num = 100
console.log(num) // 100
}
console.log(num) // 报错
```
let 和 const 的区别
1. let 声明的变量的值可以改变,const 声明的变量的值不可以改变
```javascript
let num = 100
num = 200
console.log(num) // 200
```
```javascript
const num = 100
num = 200 // 这里就会报错了,因为 const 声明的变量值不可以改变(我们也叫做常量)
```
2. let 声明的时候可以不赋值,const 声明的时候必须赋值
```javascript
let num
num = 100
console.log(num) // 100
```
```javascript
const num // 这里就会报错了,因为 const 声明的时候必须赋值
```
<script>
// console.log(a)
// var a = 100
// function test(){
// var a = 100
// }
// ES6新关键字 let变量 const常量
/*
与var区别
1. 必须先定义再使用
2. 变量重名
3. 块级作用域 {} 避免跟外面变量互相打扰
*/
//1. 必须先定义再使用
// console.log(a)
// let a = 100
// console.log(a)
//2. 变量重名
// let name = "kerwin"
// let name = "xiaomoing"
// console.log(name)
//3. 块级作用域 {}
// if(true){
// let i = 100
// console.log(i) //100
// }
// console.log(i) //报错
// let 变量
// let name = "kerwin"
// name = "xiaoming"
// const 常量 赋值完后无法改变
const obj = {
name: "kerwin"
}
// obj.name = "xiaoming" //没有覆盖 栈和堆
// obj = {name:"xiaoming"} //重新覆盖 报错
console.log(obj)
// let a
//const a
</script>
案例:块级作用域
原来var定义
for(var i=0; i<oHeaderItems.length; i++){
//自定义属性
oHeaderItems[i].dataset.index = i
oHeaderItems[i].onclick = handler
}
// console.log(i)
function handler(){
// console.log(this.dataset.index)
var index = this.dataset.index
for(var m=0;m<oHeaderItems.length; m++){
oHeaderItems[m].classList.remove("active")
oBoxItems[m].classList.remove("active")
}
oHeaderItems[index].classList.add("active")
oBoxItems[index].classList.add("active")
}
用let定义
for (let i = 0; i < oHeaderItems.length; i++) {
//自定义属性
// oHeaderItems[i].dataset.index = i
oHeaderItems[i].onclick = function () {
console.log(i)
// console.log(this.dataset.index)
var index = i
for (var m = 0; m < oHeaderItems.length; m++) {
oHeaderItems[m].classList.remove("active")
oBoxItems[m].classList.remove("active")
}
oHeaderItems[index].classList.add("active")
oBoxItems[index].classList.add("active")
}
}
2.箭头函数
-
(只有一个形参的时候)可以省略
-
{} 可以省略 只有一句代码 或 只有返回值的时候,省略return
-
没有arguments 无法拿到arguments
-
箭头函数没有this, 箭头函数this是父级作用域的,不再是谁调用它就指向谁了
2-1 箭头函数语法
-
箭头函数是 ES6 里面一个简写函数的语法方式
-
重点: 箭头函数只能简写函数表达式,不能简写声明式函数
function fn() {} // 不能简写 const fun = function () {} // 可以简写 const obj = { fn: function () {} // 可以简写 } -
语法:
(函数的行参) => { 函数体内要执行的代码 }const fn = function (a, b) { console.log(a) console.log(b) } // 可以使用箭头函数写成 const fun = (a, b) => { console.log(a) console.log(b) }const obj = { fn: function (a, b) { console.log(a) console.log(b) } } // 可以使用箭头函数写成 const obj2 = { fn: (a, b) => { console.log(a) console.log(b) } }
2-2 箭头函数的特殊性
1. 函数的行参只有一个的时候可以不写 () 其余情况必须写
const obj = {
fn: () => {
console.log('没有参数,必须写小括号')
},
fn2: a => {
console.log('一个行参,可以不写小括号')
},
fn3: (a, b) => {
console.log('两个或两个以上参数,必须写小括号')
}
}
2. 函数体只有一行代码的时候,可以不写 {} ,并且会自动 return
const obj = {
fn: a => {
return a + 10
},
fun: a => a + 10
}
console.log(fn(10)) // 20
console.log(fun(10)) // 20
3. 箭头函数内部没有 arguments 这个参数集合
const obj = {
fn: function () {
console.log(arguments)
},
fun: () => {
console.log(arguments)
}
}
obj.fn(1, 2, 3) // 会打印一个伪数组 [1, 2, 3]
obj.fun(1, 2, 3) // 会直接报错
4. 箭头函数内部没有 this,箭头函数的 this 是上下文的 this
// 在箭头函数定义的位置往上数,这一行是可以打印出 this 的
// 因为这里的 this 是 window
// 所以箭头函数内部的 this 就是 window
const obj = {
fn: function () {
console.log(this)
},
// 这个位置是箭头函数的上一行,但是不能打印出 this
fun: () => {
// 箭头函数内部的 this 是书写箭头函数的上一行一个可以打印出 this 的位置
console.log(this)
}
}
obj.fn()
obj.fun()
- 按照我们之前的 this 指向来判断,两个都应该指向 obj
- 但是 fun 因为是箭头函数,所以 this 不指向 obj,而是指向 fun 的外层,就是 window
5. 函数传递参数的时候的默认值
-
我们在定义函数的时候,有的时候需要一个默认值出现
-
就是当我不传递参数的时候,使用默认值,传递参数了就使用传递的参数
function fn(a) { a = a || 10 console.log(a) } fn() // 不传递参数的时候,函数内部的 a 就是 10 fn(20) // 传递了参数 20 的时候,函数内部的 a 就是 20- 在 ES6 中我们可以直接把默认值写在函数的行参位置
function fn(a = 10) { console.log(a) } fn() // 不传递参数的时候,函数内部的 a 就是 10 fn(20) // 传递了参数 20 的时候,函数内部的 a 就是 20- 这个默认值的方式箭头函数也可以使用
const fn = (a = 10) => { console.log(a) } fn() // 不传递参数的时候,函数内部的 a 就是 10 fn(20) // 传递了参数 20 的时候,函数内部的 a 就是 20- 注意: 箭头函数如果你需要使用默认值的话,那么一个参数的时候也需要写 ()
代码总结
<body>
<input type="text" id="mytext">
<script>
// var test1 = function(){
// console.log("11111")
// }
//箭头函数形式 () => {}
// var test2 = () => {
// console.log(2222)
// }
// test1()
// test2()
/*
1. (只有一个形参的时候)可以省略
2. {} 可以省略 只有一句代码 或 只有返回值的时候,省略return
3. 没有arguments 无法拿到arguments
4. 箭头函数没有this,
箭头函数this是父级作用域的,不再是谁调用它就指向谁了
*/
//1. (只有一个形参的时候)可以省略()
// var test = (a,b) => {
// console.log(111,a,b)
// }
// test("kerwin",100)
// 2. {} 可以省略 只有一句代码 或 只有返回值的时候,省略return
/* var test = a => {
return 100*a
}
*/
//省略后
// var test = a => 100*a
// console.log(test(10))
// var list = ["aaa","bbb","ccc"]
/*
var newlist = list.map(item=>{
reture `<li>${item}</li>`
})
*/
//省略后
// var newlist = list.map(item=>`<li>${item}</li>`)
// console.log(newlist.join(""))
/*
var test = ()=>{
console.log("111111")
}
*/
//省略后
// var test = ()=>console.log("111111")
// test()
//两个{}
/*
var test = () => {
return{
name:"kerwin"
}
}
*/
//省略后 要加()
// var test = () => ({
// name:"kerwin"
// })
// console.log(test())
//3. 没有arguments 无法拿到arguments
/*var text = function(a,b,c){
console.log(a,b,c)
}
text(1,2,3)
*/
//去掉形参
// var test = () => {
// // console.log(a,b,c)
// console.log(arguments[0],arguments[1],arguments[2])
// // console.log(Array.from(arguments))
// }
// test(1,2,3)
//4. 箭头函数没有this,
// 箭头函数this是父级作用域的
//普通函数
// mytext.oninput = function(){
// var that = this
// setTimeout(function(){
// console.log(that.value)
// },1000)
// }
//箭头函数 this是父级作用域的,不再是谁调用它就指向谁了
mytext.oninput = function(){
// var that = this
setTimeout(()=>{
console.log(this.value)
},1000)
}
//函数的默认参数,少传参数就走默认
// function test(a=1,b=2){
// return a+b
// }
var test = (a=1,b=2)=>{
return a+b
}
console.log(test(10,20))
console.log(test())
</script>
</body>
3 解构赋值
- 解构赋值,就是快速的从对象或者数组中取出成员的一个语法方式
3-1 解构对象
-
快速的从对象中获取成员
// ES5 的方法向得到对象中的成员 const obj = { name: 'Jack', age: 18, gender: '男' } let name = obj.name let age = obj.age let gender = obj.gender// 解构赋值的方式从对象中获取成员 const obj = { name: 'Jack', age: 18, gender: '男' } // 前面的 {} 表示我要从 obj 这个对象中获取成员了 // name age gender 都得是 obj 中有的成员 // obj 必须是一个对象 let { name, age, gender } = obj
3-2 解构数组
-
快速的从数组中获取成员
// ES5 的方式从数组中获取成员 const arr = ['Jack', 'Rose', 'Tom'] let a = arr[0] let b = arr[1] let c = arr[2]// 使用解构赋值的方式从数组中获取成员 const arr = ['Jack', 'Rose', 'Tom'] // 前面的 [] 表示要从 arr 这个数组中获取成员了 // a b c 分别对应这数组中的索引 0 1 2 // arr 必须是一个数组 let [a, b, c] = arr
注意
{} 是专门解构对象使用的
[] 是专门解构数组使用的
- 不能混用
<script>
// 快速的从对象和数组中获取里面的成员
var arr = ["xiaoming","teichui","shanzhen"]
// arr[arr.length-1]
let [x,y,z] = arr
console.log(x,y,z)
var a = 10
var b = 20
var [b,a] = [a,b]
console.log(a,b)
var arr2 = [1,2,[3,4,[5]]]//多维度数组 数组嵌套
// console.log(arr2[2][2][0]) //5
var [q,w,[e,r,[t]]] = arr2
console.log(t) //5
// var obj = {
// name:"kerwin",
// age:100,
// location:"dalian"
// }
// let {name,age:myage,location:mylocation} = obj
// document.write(name)
// document.write(myage)
// // document.write(location)
// document.write(mylocation)
var obj2 = {
name:"kerwin",
age:100,
location:{
province:"liaoning",
city:"dalian"
},
hobby:[111,222,333]
}
var {
name,
age,
location:{
province,
city
},
hobby:[m,n,k]
} = obj2
console.log(name,age,province,city,m,n,k) //kerwin 100 liaoning dalian 111 222 333
</script>
4. ES6的对象简写
可以省略:以及:后的
<body>
<input type="text" id="myusername">
<input type="password" id="mypassword">
<button id="mybtn">login</button>
<script>
mybtn.onclick = function () {
let username = myusername.value
let password = mypassword.value
console.log(username,password)
var obj = {
//省略前username:username,
// password:password
username,
password
}
console.log("发给后端的结构",obj)
}
var obj = {
a:1,
//省略前getName:function(){
getName(){
console.log(this.a)
}
}
obj.getName()
</script>
</body>
5. 展开运算符
- ES6 里面号新添加了一个运算符
...,叫做展开运算符
作用是把数组展开
let arr = [1, 2, 3, 4, 5]
console.log(...arr) // 1 2 3 4 5
合并数组的时候可以使用
let arr = [1, 2, 3, 4]
let arr2 = [...arr, 5]
console.log(arr2) //[1,2,3,4,5]
也可以合并对象使用
let obj = {
name: 'Jack',
age: 18
}
let obj2 = {
...obj,
gender: '男'
}
console.log(obj2)
在函数传递参数的时候也可以使用
let arr = [1, 2, 3]
function fn(a, b, c) {
console.log(a)
console.log(b)
console.log(c)
}
fn(...arr)
// 等价于 fn(1, 2, 3)
代码总结
<body>
<ul>
<li>1111</li>
<li>1111</li>
<li>1111</li>
<li>1111</li>
<li>1111</li>
</ul>
<h1>修改</h1>
<input type="text" id="myusername">
<input type="number" id="myage">
<button id="btn">修改</button>
<div id="box"></div>
<script>
// ... 展开数组
// var a = [1,2,3]
// var b = [4,5,6]
// // console.log(a.concat(b))
// var c = [...a,...b]
// console.log(c) //[1,2,3,4,5,6]
//...复制
// var a = [1,2,3]
// var b = [...a]
// b[0] = "kerwin" //[1,2,3] ['kerwin',2,3]
// console.log(a,b)
//...参数-实参-形参
// var test = function(a,b,...arr){
// console.log(arr)
// }
// test(1,2,3,4,5) //[3,4,5]
// var arr = [1,2,3]
// var test = function(a,b,c){
// console.log(a,b,c)
// }
// test(...arr) //1 2 3
// var arr = [1,2,3,5,3,6,4,8]
// var res = Math.max(...arr) //8
// console.log(res)
//...伪数组转换
// function test(){
// var arr = [...arguments]
// console.log(arr)
// }
// test(1,2,3,4,5)
// var oli = document.querySelectorAll("li")
// // console.log(oli.filter)
// var oliarr = [...oli]
// console.log(oliarr.filter) [li,li,li,li,li]
//...对象
// var obj1 = {
// name:"kerwin",
// age:100
// }
// var obj2 = {
// name:"tiechui",
// location:"dalian"
// }
// var obj = {
// ...obj1,
// ...obj2
// }
// console.log(obj) // name:'tiechui',age:100,location:'dalian'
var obj = {
name:"kerwin",
age:100,
location:"dalian",
id:"214589498387584375"
}
function render({name,age,location}){
// console.log(obj)
// var {name,age,location} = obj
box.innerHTML = `name:${name},age:${age},localtion:${location}`
}
render(obj)
btn.onclick = function(){
//最新的name和age
var name = myusername.value || obj.name
var age = myage.value || obj.age
var newobj = {
...obj,
name,
age
//...展开后,有修改的就给它放进来,在后面写
}
console.log(newobj)
//亲给后端
//重新渲染页面
render(newobj)
}
</script>
6.模版字符串
-
ES5 中我们表示字符串的时候使用
''或者"" -
在 ES6 中,我们还有一个东西可以表示字符串,就是 ``(反引号)
let str = `hello world` console.log(typeof str) // string -
和单引号还有双引号的区别
-
反引号可以换行书写
// 单引号或者双引号不能换行,换行就会报错了 let str = 'hello world' // 下面这个就报错了 let str2 = 'hello world'let str = ` hello world ` console.log(str) // 是可以使用的 -
反引号可以直接在字符串里面拼接变量
// ES5 需要字符串拼接变量的时候 let num = 100 let str = 'hello' + num + 'world' + num console.log(str) // hello100world100 // 直接写在字符串里面不好使 let str2 = 'hellonumworldnum' console.log(str2) // hellonumworldnum// 模版字符串拼接变量 let num = 100 let str = `hello${num}world${num}` console.log(str) // hello100world100- 在 `` 里面的
${}就是用来书写变量的位置
- 在 `` 里面的
-
7.ES6模块化语法
//导出
export {
//A1:A1,对象简写
A1,
A2,
test,
A_A
}
//C中引入A和B
//自己用自己引
import { A_A } from './A.js'
import { B_B } from './B.js'
function C() {
A_A()
B_B()
console.log("CC")
}
// export {
// C
// }
//默认导出,只能导出1个
export default C
<script type="module">
import CCCC from './module/C.js'
import {A1,A2,test as A_test} from './module/A.js'
//as重命名
import {B1,B2,test as B_test} from './module/B.js'
A1()
A2()
A_test()
B_test()
// console.log(C)
CCCC()
</script>