ECMASCript6简介
ECMAScript 6.0(以下简称 ES6:EcmaScript 2015)泛指 JavaScript 语言的下一代标准。
Javascript遗留问题
getElementById querySelector
声明变量:
var a = 1
var b
var b,c,d
e = 123
console.log( aa )//undefined
var aa = 123
为什么使用ES6
完善了以前的问题
增加了很多新的特性语法,方便我们开发。
ECMAScript6历史版本
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SKjLFBEU-1634209432791)(img/1-1ECMA版本.png)]
es6-es10的一个总结。
let和const命令
ES6 新增了let
命令,用来声明变量。
ES6新增了const
命令用来声明一个只读的常量。
let命令
基础用法
代码案例:
//1、 let 进行声明变量基本语法
// let b = 10
// console.log( b )//10
let命令特点
-
不存在变量提升与暂时性死区
-
不能重复声明
-
块级作用域
代码案例:
//var 支持变量提升 按照其它语言来说,其实应该报错的。
// console.log( b ) //undefined
// var a
// var b = 123
//let 的特点
//1) 没有变量提升,
// console.log( c ) //Cannot access 'c' before initialization 没有声明变量之前不能访问 。
// let c = 10
//2) 不能重复声明( 同一个作用域内不能重复定义 )
// let c = 10
// let c = 20 //'c' has already been declared
//3) 暂时性死区(同一个作用域内,声明某个变量之前都叫它的死区)
// function fn(){
// console.log( a ) //Cannot access 'a' before initialization
// let a = 20
// }
// fn() //
//4) 块级作用域 ,除了 对象的{} 其它的花括号都是块级作用域,前提条件是使用let声明的变量
/*
for/if/else/switch/while/do...while/function/for...in/
*/
// var obj = {
// key:'value'
// }
// var a = 1
// var b = 2
//花括号可以独立存在,只不过我们平时没必要写。
{
// console.log(1)
let a = 11
console.log( a )//11
{
console.log( a )// Cannot access 'a' before initialization
let a = 22
console.log( a )// 不输出
}
}
let和循环
代码案例:
<button>1</button><button>2</button><button>3</button>
<script>
var oBtns = document.getElementsByTagName('button')
// for( var i=0;i<oBtns.length;i++ ){
// oBtns[i].onclick = function(){
// alert( i )
// }
// }
for( let i=0;i<oBtns.length;i++ ){
oBtns[i].onclick = function(){
alert( i )
}
}
/*
{
let i=0
oBtns[i].onclick = function(){
alert( i )
}
}
{
let i=1
oBtns[i].onclick = function(){
alert( i )
}
}
*/
</script>
const命令
基础用法
代码案例:
const 常量名 = 常量值
const特点及建议
-
一旦声明必须赋值
-
常量的值不能修改(注意:指的是内存地址不能修改)
-
推荐使用大写名称
代码案例:
//常量的值是不会改变的,意味着只要声明就要赋值。
//后端有很多内置的数据都推荐使用常量的。
//推荐使用大写的名称,变量使用小写
// const A = '我是一个常量A'
// console.log( A )
//1. 意味着只要声明就要赋值。
// console.log( 1 )
// const B //snytax
// var a === 3
//2. 常量的值是不会改变的
const C = 123
// C = 234 //Assignment to constant variable.
//3. (注意:指的是内存地址不能修改)
// 数组、对象、函数
const O = {
a:123,
b:222
}
// O.a = 234 //未改变O的地址
O = {} //改变了O的地址
console.log( O )
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-waB0wn2f-1634209432794)(assets/1633758554850.png)]
数据类型
字符串、数值、布尔、undefined、对象、数组、函数、null
字符串扩展
模板字符串
基础用法
优点
<div id="container">
<!-- <h1>我的姓名:xxx</h1>
<h2>我的年龄:xxx</h2> -->
</div>
<script>
//声明一个字符串 : 单引号、双引号、反引号(模板字符串)
// let str1 = 'abcd'
// let str2 = ' aa"aaa" '
//1. 基本语法
// let str3 = `
// 我是一个反引号定义的字符串
// "aaaaaa"
// `
// console.log( str3 )
//2. 模板字符串可以使用 ${ 表达式 }
// console.log( ` ${1+2} ` )//3
// var username = 'zs'
// var age = 18
// console.log( `我的姓名是${username},年龄${age}` )
//3. 体会模板的含义
// let person = {
// username:'zs',
// age:15
// }
// let moban = `
// <h1>我的姓名:${person.username}</h1>
// <h2>我的年龄:${person.age}</h2>
// `
// document.getElementById('container').innerHTML = moban
//4. 一些简单的表达式
// 三目运算、字符串拼接、函数调用等表达式
var age = 20
console.log( ` ${ age >= 18 ? '成年': '不要惹熊孩子' } ` )//成年
console.log( ` ${ 'aa' + 'bbb' } ` )//aabbb
console.log( ` ${ fn() } ` )//123
function fn(){
return 123
}
</script>
新增方法
- startsWith
语法:字符串.startsWidth( 参数字符 )
描述:参数字符串是否在原字符串的头部
- endsWith
语法:字符串.endsWidth( 参数字符 )
描述:参数字符串是否在原字符串的尾部
代码案例:
// 1、startsWith( str ) | endsWith(str) 掌握
//返回值为true或false
// 比如:130
// let idcard = '130xxxxxxxxxx'
// let r = idcard.startsWith( '130' ) //true
// console.log( r )//true
// 2345
// let tel = '158xxxx2345'
// console.log( tel.endsWith( '2345' ) )//true
// console.log( tel.endsWith( '333' ) )//false
// let filename = 'xxxx.jpg'
// console.log( filename.endsWith('.jpg') )//判断是否以.jpg结尾的图片
- repeat
语法:字符串.repeat( num )
描述:返回一个新字符串,表示将原字符串重复n次
代码案例:
let str1 = 'hello'
// console.log( str1.repeat(5) )//hello*5
- padStart
语法:字符串.padStart( 目标长度,填充的字符 )
描述:字符串头部补全
代码案例:
- padEnd
语法:字符串.padEnd( 目标长度,填充的字符 )
描述:字符串尾部补全
代码案例:
//3、padStart( 位数,要填充的字符 ) 掌握
let num = 5+'' //保证是个字符串
console.log( num.padStart( 2,'0' ) )
//padEnd
console.log( num.padEnd( 2,'0' ) ) //50
Symbol
ES6 引入了一种新的原始数据类型Symbol
,表示独一无二的值。
它是 JavaScript 语言的第七种数据类型。
Symbol 值通过Symbol
函数生成。
基础用法
代码案例:
//symbol.了解即可。
//它是一种新增的数据类型。经常用在框架封装里面,js底层(Itertaor)的一些东西会用到symbol
//1. 通过Symbol函数得到一个symbol的值
// console.log( typeof Symbol )//function
let sym1 = Symbol()
// console.log( typeof sym1 )//symbol字符串
//使用 Symbol for 定义
let s3 = Symbol.for('尚硅谷');
let s3_2 = Symbol.for('尚硅谷');
console.log(s3 === s3_2);//true
//2. 特点:symbol的值是独一无二的,不做任何运算,框架封装里面使用(当作对象的key)
let sym2 = Symbol()
let sym3 = Symbol()
// console.log( sym2 == sym3 )//false symbol的值是独一无二的
// console.log( sym3 + 2 )//不做任何运算
//3. Symbol 定义 的 对象属 性 不能 使 用 for…in 循 环遍 历 ,但 是可 以 使 用Reflect.ownKeys 来获取对象的所有键名
Symbol描述符
代码案例:
//4. symbol的描述符 Symbol(描述符字符串)
let username = Symbol('username')
let age = Symbol('age')
console.log( username )
console.log( age )
应用场景
常用来模拟对象私有属性和方法。
一般常用于框架、js内置函数和对象中
代码案例1:
//框架封装里面使用(当作对象的key)
let sym1 = Symbol()
let obj = {
a:'aaaa',
[sym1]:'我是symbol当作key值'
}
// console.log( obj[sym1] )//'我是symbol当作key值'
// console.log( obj )
obj[sym1] = 'xxxxxxxx'
console.log( obj )
// for(var xxx in xxx){
// obj[] = obj[xx]
// }
代码案例2:
//框架封装里面使用(当作对象的key)
function T(){
let sym1 = Symbol()
let obj = {
a:'aaaa',
[sym1]:'我是symbol当作key值',
getAvalue:function(){
// return '我是getAvlaue函数'
return obj[sym1]
}
}
return obj
}
let o = T()
console.log( o )
console.log( o.getAvalue() )//'我是symbol当作key值'
// console.log( o.sym1 )//unefined ===> o['sym1']
// console.log( sym1 )//sym1 is not defined
数据结构
数组
数组可以存储多个数据,在JavaScript中已经学习了数组定义和一些方法包含添加、删除、获取等。es6中对数组一些方法进行了扩展。
新增方法
- Array.of
语法:Array.of( …args )
作用:Array.of 解决 new Array(1)的弊端。
代码案例:
//Array.of() => 得到一个数组:实例化一个数组
// let arr1 = new Array(5)
// let arr2 = [5]
// console.log( arr1,'arr1 array' ) //5*undefined
// console.log( arr2,'arr2 array' )// [5]
// let arr3 = new Array( 5,2,3 )
// console.log( arr3,'arr3 array' )// [5,2,3]
let arr4 = Array.of( 5 )
let arr5 = Array.of( 5,2,3 )
console.log( arr4,arr5 )//[5] [5,2,3]
- Array.from
语法:Array.from( arrayLike )
作用:把伪数组转换成数组,相对于ES5的写法,更加简洁方便
代码案例:
//1、Array.from( 伪数组 ) => 数组 es6方式
// 伪数组,把伪数组变成数组
// htmlCollections /nodelist /arguments...
let oBtns = document.getElementsByTagName('button')
console.log( oBtns )
console.log( oBtns.sort )
oBtns.sort() //sort is not a function
oBtns = Array.from( oBtns )
console.log( oBtns )
console.log( oBtns.sort )
//2、Array.prototype.slice.call(伪数组[,参数...]); es5方式
//可以理解为:改变数组的slice方法的作用域,在特定作用域(oBtns)中去调用slice方法,call()方法的第二个参数表示传递给slice的参数即截取数组的起始位置及结束位置。
oBtns = Array.prototype.slice.call(oBtns)
console.log( oBtns )
console.log( oBtns.sort )
对象
对象(object)是 JavaScript 最重要的数据类型。ES6 对它进行了重大升级,包括(数据结构本身的改变和Object对象的新增方法)
对象属性简写/函数的简写
代码案例:
/*
属性的简写(目前语法掌握),方法的简写
*/
let username = 'zs'
let age = 20
let sex = '男'
let obj = {
username,
age, // age:age
sex,
fn1:function(){
console.log('my is fn1 function',this)
},
fn2(){ //函数简写和之前的this指向是一致的(如果是相同方式去调用,则this一致)。
console.log('my is fn2 function',this)
}
}
// console.log( obj )
obj.fn1()
obj.fn2()
属性名表达式
中括号的用法 。
代码案例:
let a = 'hello'
let obj1 = {
b:'b-value',
a:'a-value',
[a]:'hello-value',
hello:'my is hello' //后面会覆盖前面
}
console.log( obj1 ) //{ a,b,hello }
//访问属性值
console.log( obj1.a )//'a-value'
console.log( obj1[a] )//'my is hello' ==> obj1.hello
console.log( obj1.hello )//'my is hello'
console.log( obj1['hello'] )//'my is hello'
console.log( obj1[hello] )//hello is not defined
新增方法**(静态方法)**
这些方法是静态方法即Object函数上的方法,因此在原型链上找不到
- Object.keys
语法:Object.keys( object )
描述:返回一个数组,成员是参数对象(可以是伪数组)自身的属性的键名
- Object.values
语法:Object.values( object )
描述:返回一个数组,成员是参数对象(可以是伪数组)自身的属性的键值
代码案例:
// Object.keys(obj) //获取对象中所有的key以数组形式返回
// Object.values(obj) //获取对象中所有的value以数组形式返回 就是为了后天讲Iterator作铺垫
let obj = {
a:'1',
b:222,
c:123
}
let keys = Object.keys( obj )
console.log( keys,'key' )
let values = Object.values( obj )
console.log( values,'value' )
- Object.assign
语法: Object.assign( target,source1,source2,… )
描述:对象的合并( 拷贝 ),将源对象(source),复制到目标对象 ( target )
代码案例:
//1. Object.assign( 新对象,源对象1,源对象2,... )
//实现浅拷贝 : 底层的浅拷贝使用的是 一层 for...in
/*
let newObj = {}
for( var attr in Obj){
newObj[attr] = obj[attr]
nwObj['arr'] = obj['arr']
}
*/
let obj1 = {
a:'my is a'
}
let obj2 = {
b:'my is b',
arr:[ 11,22,33 ]
}
let obj = {}
Object.assign( obj,obj2,obj1 )
// console.log( obj,'新对象' ) // { a,b,arr }
// obj.a = 123
// console.log( obj1,'obj1' ) //不影响源数据 a:my is a
// console.log( obj ,'obj') //a:123
obj.arr[1] = 222
console.log( obj2,'obj2' ) //影响源数据 中的引用类型数据 arr[1] : 222
console.log( obj ,'obj') //arr[1] : 222
- JSON.parse
语法:JSON.parse( jsonstr )
描述:把json字符串转换成js对象
- JSON.stringify
语法:JSON.stringify( object )
描述:把js对象转换成json字符串
目的:要深刻理解什么是json字符串
代码案例:
// JSON.parse( json字符串 ) : 把json字符串 转换成 js对象
// JSON.stringify( 对象 ) :把js对象转换成json字符串
// '[]' '{}', 无论是'[]' 还是 '{}' 里面必须是双引号,没有单引号
//key必须要带双引号,如果值为字符串必须也是双引号号
// let jsonStr = '{ username:"zs" }'
// JSON.parse( jsonStr )//Unexpected token u in JSON at position 你的字符串不是json
//正确的
// let jsonStr = `{ "username":"zs","age":20 }`
// let obj = JSON.parse( jsonStr )
// console.log( obj )
// let obj1 = {
// a:1,
// b:'hello'
// }
// console.log( JSON.stringify( obj1 ) )
// '{"a":1,"b":"hello"}'
//JSON字符串就不应该有函数
let obj1 = {
a:2,
fn:function(){
},
b:'hello'
}
// console.log( obj1 )
console.log( JSON.stringify( obj1 ) )
// '{"a":2,"b":"hello"}' 函数会丢失 如果原数据没有函数,那么深拷贝可以放心使用
Set(集合)
ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
基本用法
代码案例:
let set1 = new Set( 数组|伪数组 ) =》 没有重复值的set结构
掌握数组的去重即可。
function uniqueData(arr){
let set1 = new Set( arr )
let arr1 = Array.from( set1 )
return arr1
//return Array.from( new Set( arr ) )
}
常见方法:了解即可
写在对象.__proto__的方法 => 实例对象的函数原型 prototype
- size 获取set集合的长度
- add(值) 给集合添加值,返回新set
- delete(值) 删除某个值,返回布尔值,表示是否删除成功
- has(值) 查询这个值是否时集合的成员,返回布尔值
- clear() 清空集合,没有返回值
代码案例:
let set1 = new Set( [20,30,20,30,50] )
// console.log( set1 )
// console.log( set1.__proto__ === Set.prototype ) //true
/*
add(值) 给集合添加值,返回新set
delete(值) 删除某个值,返回布尔值,表示是否删除成功
has(值) 查询这个值是否时集合的成员,返回布尔值
clear() 清空集合,没有返回值
*/
// set1.add(11)
// set1.add(11)
// set1.delete( 20 )
// console.log( set1.has( 30 ) )//true
// console.log( set1.has( 31 ) )//false
set1.clear()
console.log( set1 )
Map
ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
map数据结构是对 对象的一种扩展 ,类似于对象。
对象只能用字符串或symbol来当作对象的key。
但是其它一些程序语言中可以用任意数据类型当作key,但对象不支持,所以发明了一个map数据结构
map可以使用任意数据类型当作map的key。
基本用法
代码案例:
let map1 = new Map( [ [key1,value1],[key2,value2],... ] )
let arr = [11,22]
let map1 = new Map( [
[false,'我是布尔值当作key'],
[ null,'我是null当作key' ],
[ arr,'我是数组当作key' ]
] )
// console.log( map1,'map1' )
常见方法
- size 获取Map的长度
- set(key,val) 添加一条数据
- get(key) 根据key获取val
- has(key) 是否存在key
- delete(key) 删除某条数据
- clear() 清空所有数据
console.log( map1.get( arr ) ) //我是数组当作key
map1.set( 11,'我是number当作key' )
console.log( map1 )
运算符表达式
变量的解构赋值
解构赋值
概念及意义
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构
数组解构
解构 赋值
解构 : 解析结构。这是es6非常重要且非常方便的一个特性,就是方便开发者从数组或对象中进行取值。
数组的解构
let [变量1,变量2,...] = [value1,value2,...]
完全解构
//1. 完整的数组解构
// let [ a,b,c,d ] = [20,201,30,55]
// console.log( a,b,c,d,'完整的数组解构' )
不完全解构
//2. 不完全解构
// let [ a,b,c] = [20,201,30,55]
// console.log( a,b,c,'不完全解构' )
解构失败
//3.解构失败
// let [ a,b,c] = [20,201]
// console.log( c,'undefined值' ) //相当于声明了c变量且未赋值
解构默认值
//4. 默认值
// let [ a,b,c=33] = [20,201]
// console.log( c,'c的默认值生效' )
缺省
例子:
//5. 缺省
// let [ ,b,c] = [20,201,30]
// console.log( b,c,'缺省' )
数组解构应用(数据交换)
代码案例:
let a = 10
let b = 20
;[a,b] = [b,a] //前面不能加let
console.log( a,b ) //20,10
对象解构
对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,而对象的属性没有次序。
语法:
语法1:完整的语法
{ key2:变量2,key1:变量1,... } = { key1:value1,key2:value2,... }
语法2:简写语法
{ key2,key1,... } = { key1:value1,key2:value2,... }
使用已知的key当作变量
完整语法解构
//1. '完整写法'
// let { username:uname,age:uage } = { username:'zs',age:20 }
// console.log( uname,uage)
简写语法解构
//2. 简写写法
// let { username,age,sex } = { sex:'男', username:'zs',age:20 }
// console.log( username,age,sex)
解构默认值
//3. 默认值
// let { username:uname,age:uage,sex='女' } = { username:'zs',age:20 }
// console.log( sex,'默认值生效' )
let { username:uname,age:uage,sex='女' } = { username:'zs',age:20,sex:'男' }
console.log( sex,'替换默认值' )
解构失败
代码案例:
//4. 解构失败
// let person = { username:'zs',age:20 }
// let { username:uname,age:uage,sex:aa } = person
// let aa = person.sex
console.log( aa )//'undefined值,解构失败'
使用场景
当函数参数比较多时进行优化。
代码案例:
//必须按顺序传递实参
function setProForEle(ele, pro, value) {
//ele:元素 pro:样式属性 value:样式属性对应的值
console.log(ele, pro, value)
//ele.style[pro] = value
}
// setProForEle( '元素','height','100px' )
// setProForEle( 'height','100px','元素' )//不行
//1.解决顺序问题
// function setProForEle2( option ){
// { ele, pro, value } = option
// console.log( option.ele,option.pro,option.value )
// }
// setProForEle2( {
// ele:'我是元素2',
// pro:'height',
// value:'30px'
// } )
//2.解决顺序问题
function setProForEle3({ ele, pro, value }) {
// 元素、样式属性、样式属性对应的值
/*
{ ele, pro, value } = {
ele: '我是元素33',
pro: 'height',
value: '30px'
}
*/
console.log(ele, pro, value)
}
setProForEle3({
ele: '我是元素33',
pro: 'height',
value: '30px'
})
多层解构的补充(了解)
let obj = {
a:1,
b:2,
c:[ 33,44,55 ]
}
//obj.c[1]
let { c:[,c1] } = obj
console.log( c1 )
关于js分号的补充
// 以 [],(),`` 开头的,必须加分号,在它们前面
console.log( 10 )
let a = 20
console.log( a )
let b = 30
;[a,b] = [b,a]
console.log( a,b,'交换' )
;(function(){
console.log( 2222 )
})()
;``
{ ele, pro, value } = option
// console.log( option.ele,option.pro,option.value )
// }
// setProForEle2( {
// ele:'我是元素2',
// pro:'height',
// value:'30px'
// } )
//2.解决顺序问题
function setProForEle3({ ele, pro, value }) {
// 元素、样式属性、样式属性对应的值
/*
{ ele, pro, value } = {
ele: '我是元素33',
pro: 'height',
value: '30px'
}
*/
console.log(ele, pro, value)
}
setProForEle3({
ele: '我是元素33',
pro: 'height',
value: '30px'
})
### 多层解构的补充(了解)
```js
let obj = {
a:1,
b:2,
c:[ 33,44,55 ]
}
//obj.c[1]
let { c:[,c1] } = obj
console.log( c1 )
关于js分号的补充
// 以 [],(),`` 开头的,必须加分号,在它们前面
console.log( 10 )
let a = 20
console.log( a )
let b = 30
;[a,b] = [b,a]
console.log( a,b,'交换' )
;(function(){
console.log( 2222 )
})()
;``