我们所说的ES5和ES6其实就是在js语法的发展过程中的一个版本而已
我们写代码的时候就要考虑哪些方法是ES5或者ES6的,看看是不是浏览器都支持
定义变量
let
-
定义变量
-
我们以前都是使用
var
关键字来声明变量的 -
【注】
- 不允许重复声明变量
- 必须先定义,在使用(防止了变量提升)
- 在块级作用域中
let
定义的变量只存在于块级作用域内部,即{}
中,在块级作用域外部是访问不到的 - 变量的值可以随意修改,任意类型
const
-
定义常量
-
常量:不允许重新赋值
-
【注】
-
const在初始化的时候必须赋值,否则会报错
-
不能重复声明
-
防止变量提升,要先定义后使用
-
具备块级作用域
-
值的修改
- 如果是基本数据类型,不可以修改
- 如果是引用类型,可以修改它的属性和方法,不能修改类型和地址
-
对字符串的增强
includes()
:包含指定字符,返回true或falserepeat(n)
:重复startsWith()
:是否在开始位置,返回true或falseendsWith
:是否在结束位置,返回true或falsepasStart()
:es7 前面填充padEnd()
:es7 后面填充- 字符串模版:反引号 ``
对数组增强
Array.from()
:把伪数组变成真数组Array.of()
:将一组值转换成数组find()
:找到第一个符合条件的数组成员,没有返回undefinedfindIndex()
:找到第一个符合条件的数组成员的索引值,没有返回-1
对象增强
key值
- 在对象中key值与赋给key值的变量一致时,可以把
:变量
省略
<input type="text" name="" id="myusername">
<input type="text" name="" id="mypassword">
<button id="btn">login</button>
<script>
btn.onclick = function(){
let username = myusername.value
let password = mypassword.value
console.log(username,password)
var obj = {
username:username,
password:password
}
//简写
var obj = {
username,
password
}
console.log("提交给后端的数据",obj)
}
</script>
函数
-
在对象中函数可以简写,省略
:function
var obj = {
name:"cxm",
getName:function(){
console.log(this.name)
}
}
//简写
var obj = {
name:"cxm",
getName(){
console.log(this.name)
}
}
obj.getName()
新增方法
Object.assign()
-
合并对象
- 原理:把
()
内第一个参数后边的参数,放入第一个参数中 - 【注】相同的key值会覆盖
- 原理:把
var obj1 = {id: 1,name: "杨超越"}
var obj2 = {name: "虞书欣",age: 25}
// 合并一个新对象
var obj3 = Object.assign({}, obj1, obj2)
console.log(obj3) //{id: 1, name: '虞书欣', age: 25}
// 覆盖(把obj2的数据放入obj1中)
Object.assign(obj1, obj2)
console.log(obj1) //{id: 1, name: '虞书欣', age: 25}
Object.is(m,n)
- 比较是否相等,比较 恒等于
===
console.log(NaN===NaN) //false
console.log(Object.is(NaN,NaN)) //true
console.log(-0===0) //true
console.log(Object.is(-0,0)) //false
//上边两个记住,特殊的
console.log(Object.is(10,"10")) //false
console.log(Object.is(true,10)) //false
console.log(Object.is(10,10)) //true
console.log(Object.is({},{})) //false 引用数据类型,存储地址不同
对函数增强
函数的默认参数
-
在定义形参的的时候给一个初始值
- 如果外部没有传实参就使用设置的默认参数
- 传值就使用传入的参数
function fn(num = 100) {
console.log(num)
}
fn(10) //10
fn() //100
箭头函数
语法:
() => {函数体}
简写
()
里面可以填形数,当只填一个参数的时候,()
可以省略,两个及以上参数不可以省略
var test = (a) => {
console.log(a)
}
//可以简写成
var test = a => {
console.log(a)
}
test("caoxinmei")
- 当函数体中只有一句代码或者只有返回值的时候
{}
和return
可以省略
var test = a => {
console.log(a*10)
}
//可以简写成
var test = a => console.log(a*10)
test(10)
//map映射
var list = ['111','222','333']
var newlist = list.map(function(item){
return `<li>${tiem}</li>`
})
//可以简写为
var newlist = list.map(item => `<li>${tiem}</li>`)
注意点
- 当返回值是一个对象的时候,在简写为箭头函数时,需要加上
()
,以防止箭头函数误认这个对象为函数体,报错。
var test = () => {
return {name:"caoxinmei"}
}
//可以简写为
var test= () => ({name:"caoxinmei"})
-
箭头函数没有arguments伪数组属性
-
箭头函数不能被实例化
var fn = () => {}
console.log(fn)
var f = new fn() //报错:fn is not a constructor 没有构造器
this指向问题
-
箭头函数的this指向上下文,箭头函数本身没有this ,利用bind, call, apply无法改变this指向
-
它默认情况会window (因为箭头函数的执行环境是全局window)
-
它无法被实例化,不能被new
-
有两种说法(倾向于第二种)
- 箭头函数没有this
- 箭头函数this是指父级作用域
展开运算符
...
数组方面
...
合并数组
var a = [1,2,3]
var b = [4,5,6]
console.log(a.concat(b)) //数组拼接方法
var c = [...a,...b] //展开运算
console.log(c)
...
复制
var a = [1,2,3]
var b = a.slice() //数组方法
var c = [...a] //展开运算符
console.log(b,c)
...
参数
形参
//普通传参
var test = function (a, b, c) {
console.log(a, b, c)
}
test(1, 2, 3)
//...展开运算符
var test1 = function(...arr){
console.log(...arr)
}
test1(1,2,3)
//...展开运算符只能放在最后
var test1 = function(a,b,...arr){
console.log(a,b,...arr)
}
test1(1,2,3,4)
实参
var arr = [1,2,3]
var test = function(...arr){
console.log(...arr)
}
test(arr[0],arr[1],arr[2]) //普通传参
test(...arr) //展开运算符传参
伪数组转换
function test(){
var arr = [...arguments]
console.log(arr)
}
test(1,2,3,4,5) //(5)[1,2,3,4,5]
var oli = document.querySelectorAll("li")
var oliarr = [...oli]
console.log(oliarr) //(5)[li,li,li,li,li]
对象
合并对象
var obj1 = {
name:"cxm"
age:21
}
var obj2 = {
location:"changsha"
}
var obj = {...obj1,...obj2}
console.log(obj)
- 注 : 相同的key值会被覆盖
小案例
- 案例描述 : 动态修改姓名和年龄,并在页面中显示出来
<body>
<input type="text" name="" id="username" placeholder="姓名">
<input type="number" name="" id="userage" placeholder="年龄">
<input type="text" name="" id="userlocation" placeholder="地址">
<button id="btn">修改</button>
<div id="box"></div>
<script>
var obtn = document.getElementById("btn")
var obox = document.getElementById("box")
var obj = {
name:"cxm",
age:21,
location:"changsha",
id:"256589568789556"
}
function fn({name,age,location}){
// 通过解构赋值的方式传参{name,age,location}
obox.innerHTML = `name:${name}<br>age:${age}<br>location:${location}`
}
fn(obj)
obtn.onclick = function(){
// 使用逻辑运算符"或",防止出现空值的情况
var name = username.value || obj.name
var age = userage.value || obj.age
var location = userlocation.value || obj.location
//定义一个空对象来接收改变过后的对象
var newobj = {
...obj, //展开运算符,展开对象obj
//通过key值相同可以覆盖的原理,把新获取的值放进对象中
name, //对象简写,name:name,
age, //对象简写
location
}
fn(newobj)
}
</script>
</body>
修改前:
修改后:
解构赋值
- 快速的从对象和数组中获取里面的成员
- 解构赋值语法是一种 Javascript 表达式。通过
解构赋值
,可以将属性/值从对象/数组中取出,赋值给其他变量。 - 【关键】 解构赋值的变量与数组或对象的结构一致
解构数组
变量声明并赋值时的解构
- 解构数组时,只要位置一一对应就可以
- 内容可以不同
var arr = ["one", "two", "three"];
var [a, b, c] = arr;
console.log(a); // "one"
console.log(b); // "two"
console.log(c); // "three"
undefined
- 如果解构不成功,变量的值为undefined。
var [foo] = [];
var [bar, foo] = [1];
console.log(bar,foo) //1,undefined
交换变量
-
在一个解构表达式中可以交换两个变量的值。
-
没有解构赋值的情况下,交换两个变量需要一个临时变量。
var a = 3
var b = 30
var [b,a] = [a,b]
console.log(a,b) //30,3
多维数组
//把数组中的数字5取出来
var arr = [1,2,[3,4,[5]]]
//数组索引方式
console.log(arr[2][2][0])
//采用解构赋值的方式
var [a,b,[c,d,[f]]] = arr
console.log(f)
解构对象
基本赋值
var obj = {
name:"cxm",
age:21,
city:"changsha"
}
var {name,age,city} = obj //{name,age,city}内顺序可以打乱
console.log(name,age,city)
给新的变量名赋值
- 可以从一个对象中提取变量并赋值给和对象属性名不同的新的变量名。
var obj = {
name:"cxm",
age:21,
city:"changsha"
}
var {name:myname,age:myage,city:mycity} = obj
console.log(myname,myage,mycity)
解构嵌套对象和数组
var obj = {
name: "cxm",
age: 21,
city: ["chenzhou", "changsha", "shenzhen"],
habby: {
habby1: "wa",
habby2: "wawa",
habby3: "wawawa"
}
}
var {name, age, city:[a, b, c], habby:{habby1:yi,habby2:er,habby3:san}} = obj
console.log(name, age, a, b, c, yi, er, san)
ES6新增方法和数据类型
新增方法
Set 集合
-
成员不能重复,(会自动去重)
-
add() 添加
- 返回值是变化后的新集合
-
delete() 删除
- 删除成功返回true,失败返回false
-
has() 有
- 判断集合中是否有这个元素,有返回true,没有返回false
-
forEach() 遍历
-
clear() 清除
-
转数组
- Array.from()
- 展开运算符
...
var set = new Set([1,3,4,7,1,3,4,7]) //初始值
console.log(set) //Set(4) {1, 3, 4, 7},成员不能重复
// add() 添加
// 返回值是变价后的新集合
console.log(set.add(7)) //Set(4) {1, 3, 4, 7}
console.log(set.add(9)) //Set(5) {1, 3, 4, 7, 9}
// delete() 删除
// 删除成功返回true,失败返回false
console.log(set.delete(7)) //true
console.log(set.delete(71)) //false,集合中没有71这个元素
// has() 有
// 判断集合中是否有这个元素,有返回true,没有返回false
console.log(set.has(1)) //true
console.log(set.has(71)) //false
// forEach() 遍历
set.forEach(function(val1,val2,set){
console.log(val1,val2,set)
})
// clear() 清除
// set.clear()
// console.log(set) //Set(0) {size: 0}
// 转数组
// 1.Array.from()
var arr= Array.from(set)
console.log(arr) //(4) [1, 3, 4, 9]
// 2.展开运算符
var arr = [...set]
console.log(arr) //(4) [1, 3, 4, 9]
// 最短去重方式
var arr = [1,2,4,1,2,4,4,3,3,5]
var newArr = [...new Set(arr)]
console.log(newArr) //(5) [1, 2, 4, 3, 5]
WeakSet
-
对象 不能重复
-
add() 添加
-
delete() 删除
- 返回值true或false
-
has() 有
- 返回值true或false
// WeakSet 对象不能重复
var wset = new WeakSet([{ id: 1, name: "杨超越" }, { id: 1, name: "杨超越" }])
//有两个对象,原因:对象的地址不同
console.log(wset) // WeakSet {{…}, {…}}
// add() 添加
var obj = { id: 1, name: "虞书欣" }
wset.add(obj)
console.log(wset.add(obj)) //WeakSet {{…}, {…}, {…}}
wset.add(obj)//添加不成功,此时obj地址一致
// delete() 删除
console.log(wset.delete(obj)); //true
// has() 有
console.log(wset.has(obj)); //false
Map 超对象
-
Map 是一个“超对象”,其 key 除了可以是 String 类型之外,还可以为其他类型(如:对象)
-
语法:
new Map([[key,value],[key,value]])
-
方法:
- size:返回成员总数。
- set(key, value):设置一个键值对。
- get(key):读取一个键。
- has(key):返回一个布尔值,表示某个键是否在Map数据结构中。
- delete(key):删除某个键。
- clear():清除所有成员。
- keys():返回键名的遍历器。
- values():返回键值的遍历器。
- entries():返回所有成员的遍历器。
- forEach():遍历
// 初始化
var map = new Map([
[1, "杨超越"],
["sex", "女"],
[2, true],
["3", { hobby: "爱好" }],
[3, 3]
])
console.log(map) //Map(5) {1 => '杨超越', 'sex' => '女', 2 => true, '3' => {…}, 3 => 3}
// set(key,value) 添加
// 返回添加之后的新Map对象
console.log(map.set("name", "aaaa"))
console.log(map.set(1, "11111")) //key值相同会覆盖
// delete(key) 删除
// 返回值true和false
console.log(map.delete(1)) //true
console.log(map.delete(10)) //false
// has(key) 有
// 返回值true和false
console.log(map.has(2)) //true
console.log(map.has(10)) //false
// get(key) 获取
console.log(map.get("sex")) //女
// clear() 清除
// map.clear()
// console.log(map)
// keys() 获取所有的键
console.log(map.keys()) // MapIterator {'sex', 2, '3', 3, 'name'}
// 转为数组
console.log([...map.keys()]) //(5) ['sex', 2, '3', 3, 'name']
// values() 获取所有的值
console.log(map.values()) // MapIterator {'女', true, {…}, 3, 'aaaa'}
// map.entries()
console.log( map.entries()) // MapIterator {'sex' => '女', 2 => true, '3' => {…}, 3 => 3, 'name' => 'aaaa'}
// forEach() 遍历
map.forEach(function(val,key,map){
console.log(val,key,map)
})
// for of遍历
// -----遍历键和值-----
// 默认是map.entries()
for(let [k,v] of map){
console.log(k,v)
}
// ------遍历键-----
for(let k of map.keys()){
console.log(k)
}
// -----遍历值-----
for(let v of map.values()){
console.log(v)
}
新增数据类型 Symbol
- Symbol 是ES6引入的一种新的数据类型(值类型),来表示独一无二的值
创建
- 创建Symbol值 ,不能添加new
//没有参数的情况
var s1 = Symbol()
var s2 = Symbol()
console.log(s1, s2) // Symbol() Symbol()
console.log(s1 == s2) // false
console.log(s1 === s2) // false
//有参数
var s1 = Symbol("111")
var s2 = Symbol("111")
console.log(s1, s2) //Symbol(111) Symbol(111)
console.log(s1 == s2) //false
console.log(s1 === s2) //false
Symbol.for( )
var s3 = Symbol.for("aaaa") //第一次,询问是否有aaaa这个标记,如果没有就创建,有就直接使用
var s4 = Symbol.for("aaaa") //第二次,询问是否有aaaa这个标记,前面s3创建过,现在直接拿来用,不再创建
var s5= Symbol.for("aaaa")
console.log(s3===s4) //true
console.log(s4===s5) //true
类型
var s6 = Symbol("s6")
console.log(typeof s6) //symbol
for.in 和 for.of
数组
-
for.of遍历数组,得到的是值,根据长度遍历
-
for.in遍历数组,得到的是下标(key),不会遍历空的成员
var arr = [11, 22, 33, 44]
arr.length = 10
// for.of
console.log("--------for...of------")
for (let val of arr) {
console.log(val)
}
// for.in
console.log("--------for...in------")
for (let key in arr) {
console.log("下标:" + key, "值:" + arr[key])
}
对象
-
for.in遍历对象,得到的是键(key),还会遍历原型的属性和方法
-
for.of不能直接遍历对象,会提示没有迭代器(iterable)
-
使用Object.keys、Object.values、Object.entires
-
给对象添加迭代器
// 添加迭代器语法 [Symbol.iterator](){ return{ next(){ return{ value:要返回的内容 done:true/false //true停止,false继续 } } } }
- 还能遍历ES6的map,但是for.in不可以
-
var obj = {
id: 1001,
name: "杨超越",
sex: "女",
// 添加迭代器
[Symbol.iterator]() {
var arr = Object.values(this)
var index = -1
return {
next() {
index++
return {
value: arr[index],
done: arr.length == index
}
}
}
}
}
Object.prototype.address = "中国"
// for.in
// 遍历原型的属性和方法
console.log("--------for.in------")
for (let key in obj) {
console.log(key, obj[key])
}
// for.of
console.log("-------for.of--------")
for (let key of obj) {
console.log(key) //obj is not iterable 提示没有迭代器
}
console.log("------Object.keys()---------")
for (let key of Object.keys(obj)) {
console.log(key, obj[key])
}
console.log("-------Object.values()--------")
for (let val of Object.values(obj)) {
console.log(val)
}
console.log("-------Object.entries()--------")
for (let [k, v] of Object.entries(obj)) {
console.log(k, v)
}
class 类
写法
-
类 - -> 对象 - - > 属性 + 方法
-
语法 :
class 函数名{
//构造器函数 --> 属性
constructor(){
函数体
}
//原型 --> 行为(方法)
方法名(){
方法体
}
}
-
【注】
- constructor方法是类的默认方法,通过new命令实例化对象时,自动调用该方法
- 类的首字母大写,即函数名的首字母大写
class Person {
// 属性
constructor(name, age, sex) {
this.name = name,
this.age = age,
this.sex = sex
}
// 行为(方法)
eat(food) {
console.log(`我${this.name}爱吃:${food}`)
}
run() {
console.log(`${this.name}--连夜提桶跑路`)
}
}
// 实例化
var p1 = new Person("杨超越", 23, "女")
p1.eat("蔬菜沙拉")
p1.run()
var p2 = new Person("丁禹兮", 26, "男")
p2.eat("土豆")
p2.run()
继承
-
关键字 : extends super
-
子类拥有父类的属性和方法
-
静态属性和静态属性是能被继承的,但是不能通过new的方式去访问静态方法和属性
// 父类
// 人
class Person {
constructor(name, age, sex) {
this.name = name
this.age = age
this.sex = sex
}
eat(food) {
return `我${this.name},最爱吃${food}`
}
run(num) {
return `我..${this.name},今年${this.age},我今年第${num}次提桶跑路了`
}
}
// 子类
// 程序员
class Programmer extends Person {
// 继承属性
constructor(name, age, sex, hair) {
super(name, age, sex)
this.hair = hair
}
// 新增方法
coding() {
console.log("没日没夜的写代码")
}
// 重写
// 重写父类的方法
run(num) {
return `我..${this.name},直接跑路,不提桶了`
}
}
// 实例化
// 父类
var p = new Person("杨超越", 25, "女")
console.log(p.eat("蔬菜沙拉"))
console.log(p.run(2))
//子类
var p1 = new Programmer("某某某",26,"女")
// 继承父类的方法
console.log(p1.eat("肉"))
// 重写父类的方法
console.log(p1.run())
// 新增方法
p1.coding()