let const 命令
-
es5 有两个作用域:全局作用域、函数作用域,es6新增了一个作用域:块级作用域
-
let 声明块级作用域变量
-
const 声明常量,声明时必须赋值
-
使用es6语法,强制开启严格模式,相当于es5中加入"use strict"
-
// const 声明的常量无法改变 const obj = {a: 1}; obj.b = 2 // const 声明的对象,该变量为一个指针,指针无法改变,但是对象能修改
解构赋值
数组解构赋值
{
let a, b, rest
;[a, b, ... rest] = [1,2,3,4,5,6]
console.log(a, b, rest) // 1 2 [ 3, 4, 5, 6 ]
}
// 获取函数返回值
{
function f () {
return [1, 2, 3, 4, 5, 6, 7, 8, 9]
}
// let a, b
// ;[a, b] = f()
let [a, ,...b] = f()
console.log(a, b) // 1 [ 3, 4, 5, 6, 7, 8, 9 ]
}
// 交换变量
{
let a = 1, b = 2
;[a, b] = [b, a]
console.log(a, b)
}
对象解构
{
let a, b, rest
;({a, b} = {a: 1, b: 2}) // 需要加圆括号,否则js解释器会将花括号解析为代码块
console.log(a, b)
}
{
// 把对象中的p赋值给myP,对象中的q赋值给myQ(默认为3)
// 冒号后面的是let声明的变量,而冒号前面的是对象中的key,等号后面为默认值
let {p:myP, q:myQ=3} = {p: 100}
console.log(myP, myQ)
}
// 解析 对象(服务端响应的json)
{
let json = {
title: 'this is a title',
person: [
{
'name': 'Tom',
'age': 18
},
{
'name': 'Jack',
'age': 21
}
]
}
let {title:myTitle, person:[{name: myName1}, {name: myName2}]} = json
console.log(myTitle, myName1, myName2) // this is a title Tom Jack
}
正则扩展
构造函数
{
// let regex = new RegExp('xyz', 'i')
// let regex = new RegExp(/xyz/i)
// es6 允许第一个参数是//正则表达式, 第二个参数是flags, 会覆盖第一个参数的flags
let regex = new RegExp(/xyz/i, 'gi')
console.log(regex.test('Xyz'))
console.log(regex.flags)
}
y 修饰符
/**
* y 修饰符的作用与 g 修饰符类似,也是全局匹配,后一次匹配都从上一次匹配成功的下一个位置开始。
* 不同之处在于,g 修饰符只要剩余位置中存在匹配就可,而 y 修饰符确保匹配必须从剩余的第一个位置开始
**/
let str1 = 'bbb_bb_b'
let reg1 = /b+/g
let reg2 = /b+/y
console.log('1', reg1.exec(str1), reg2.exec(str1))
console.log('2', reg1.exec(str1), reg2.exec(str1))
// 正则对象是否开启了y 修饰符
console.log(reg1.sticky, reg2.sticky)
u 修饰符
/**
* ES5不支持四个字节的 UTF-16 编码,会将其识别为两个字符
* u 用来正确处理大于 \uFFFF 的Unicode字符
* **/
// false
console.log(/\u{61}/.test('a'))
// 加 u 修饰符才会被识别为Unicode码
// true
console.log(/\u{61}/u.test('a'))
// console.log(`\u{20bb7}`)
let str1 = '𠮷'
// false
console.log(/^.$/.test(str1))
// true
console.log(/^.$/u.test(str1))
// false
console.log(/𠮷{2}/.test('𠮷𠮷'))
// true
console.log(/𠮷{2}/u.test('𠮷𠮷'))
字符串扩展
取码值
{
// let s = '𠮷'
// console.log(s.length)
// console.log(0, s.charAt(0))
// console.log(1, s.charAt(1))
// console.log(0, s.charCodeAt(0))
// console.log(1, s.charCodeAt(1))
let s1 = '𠮷a'
// es5 charCodeAt
console.log(s1.length)
console.log(0, s1.charAt(0))
console.log(1, s1.charAt(1))
console.log(2, s1.charAt(2))
console.log(0, s1.charCodeAt(0))
console.log(1, s1.charCodeAt(1))
console.log(2, s1.charCodeAt(2))
console.log('========')
// es6 codePointAt
console.log(s1.codePointAt(0))
console.log(s1.codePointAt(0).toString(16))
console.log(s1.codePointAt(1))
console.log(s1.codePointAt(2))
}
根据码值取字符
// es5 fromCharCode
console.log(String.fromCharCode("0x20BB7"))
// es6 fromCodePoint 能处理大于2个字节的unicode字符
console.log(String.fromCodePoint("0x20BB7"))
遍历字符串
{
let str = '\u{20BB7}abc'
for (let i = 0; i < str.length; i ++) {
console.log(str[i])
}
for (let code of str) {
console.log(code)
}
}
常用方法
{
let str = 'string'
console.log(str.includes('i'))
console.log(str.startsWith('str'))
console.log(str.endsWith('ing'))
console.log(str.repeat(3))
// 补白
console.log('1'.padStart(3, '0'))
console.log('1'.padEnd(3, '0'))
}
模版字符串
{
let a = 'aaa'
let b = 'bbb'
let m = `a is ${a}, b is ${b}`
console.log(m)
}
标签模版
作用: 防xss攻击;多语言转换(中文、英文。。。)
{
let obj = {
a: 'aaa',
b: 'bbb'
}
console.log(abc`a is ${obj.a}! b is ${obj.b}`)
function abc (s, v1, v2) {
console.log(s, v1, v2)
return s + v1 + v2
}
}
String.raw
{
console.log('a\nb\tc')
console.log(String.raw`a\nb\tc`)
}
数值扩展
进制
{
// 二进制
console.log(0b1000)
// 八进制
console.log(0o17)
}
Number.isFinite 和 Number.isNaN
{
// 判断是否是一个有限的数字
console.log('15', Number.isFinite(15)) // trun
console.log('15', Number.isFinite('15')) // false Number.inFinite方法更严格,只能为Number类型
console.log('15', isFinite('15')) // true isFinite()函数,没有那么严格
console.log('NaN', Number.isFinite(NaN)) // false
// 判断是否是数字 true不是,false是
console.log('NaN', Number.isNaN(NaN)) // true
console.log('0', Number.isNaN(0)) // false
console.log('0', Number.isNaN('0')) // false
console.log('0', isNaN('0')) // false
}
判断是否是整数 是否是安全整数
{
console.log('25', Number.isInteger(25))
console.log('25.0', Number.isInteger(25.0)) // true
console.log('25.1', Number.isInteger(25.1)) // false
console.log('25 str', Number.isInteger("25")) // false
}
{
console.log(Number.MAX_SAFE_INTEGER)
console.log(Number.MIN_SAFE_INTEGER)
// 判断是否是安全整数
console.log(Number.isSafeInteger(9007199254740999))
console.log(Number.MAX_VALUE)
console.log(Number.MIN_VALUE)
}
取整和判断整数
{
// 取整
console.log(Math.trunc(4.1)) // 4
console.log(Math.trunc(-4.1)) // -4
// 判断 + - 0
console.log(Math.sign(5)) // 1
console.log(Math.sign(0)) // 0
console.log(Math.sign(-5)) / -1
console.log(Math.sign('5')) // 1
console.log(Math.sign('-5')) // -1
console.log(Math.sign('foo')) // NaN
console.log(Math.sign('0')) // 0
}
还有立方根,三角函数等api
数组扩展
Array.from
{
let obj = {
0: 1,
1: 2,
length: 5
}
let arr = Array.from(obj)
console.log(arr) // [ 1, 2, undefined, undefined, undefined ]
let arr1 = Array.from([1,2,3], function (item) {
return item * 2
})
console.log(arr1) // [ 2, 4, 6 ]
let arr2 = Array.from(obj, function (item) {
return item * 2
})
console.log(arr2) //[ 2, 4, NaN, NaN, NaN ]
}
Array.fill
{
console.log([1, 2, 3, undefined].fill(7)) // [ 7, 7, 7, 7 ]
// 第一个参数替换内容,第2、3个参数,替换的位置
console.log(['a', 'b', 'c'].fill(7,1,3)) // [ 'a', 7, 7 ]
}
// copyWithin方法,内部替换
{
// 从0开始替换,替换的位置为4到6-1
console.log([1,2,3,4,5,6].copyWithin(0,4,6)) // [ 5, 6, 3, 4, 5, 6 ]
}
.keys() 、.values()、.entires() 遍历
{
//
for (let index of ['1', 'c', 'ks'].keys()) {
console.log(index)
}
for (let index of ['1', 'c', 'ks'].values()) {
console.log(index)
}
for (let [index, value] of ['1', 'c', 'ks'].entries() ){
console.log(index, value)
}
}
.find()、.findIndex() 查找
{
console.log([1,2,3,4,5,6].find(function (item) {
return item > 3
}))
console.log([1,2,3,4,5,6].findIndex(function (item) {
return item > 3
}))
}
函数扩展
参数默认值
{
function test (x, y = 'world') {
console.log(x, y)
}
test('hello')
}
参数作用域问题
{
let x ='test'
function test1 (x, y=x) {
console.log('作用域', x, y)
}
test1('kill') //作用域 kill kill
function test2 (c, y=x) {
console.log('作用域', c, y)
}
test2('kill') // 作用域 kill test
}
rest 参数
rest参数之后不能再有其它参数了
{
function test3 (first, ...arg) {
for (let v of arg) {
console.log(v)
}
}
test3(1,2,'a')
}
扩展运算符
扩展运算符 和 rest 是“逆运算”, f(...[1, 2, 3])
把数组拆成多个参数传入f
{
console.log(...[1, 2, 3])
console.log(0, ...[1, 2, 3])
function test (...arg) {
console.log(arg)
}
test(0, ...[1, 2, 3])
}
箭头函数
{
let arrow0 = v => v * 2
let arrow1 = (v) => v * 2
let arrow2 = (v) => {return v * 3}
console.log(arrow0(3)) // 6
console.log(arrow1(4)) // 8
console.log(arrow2(5)) // 15
}
尾调用优化
尾调用优化 ” ( Tail call optimization ),即只保留内层函数的调用帧。如果所有函数都是尾调用,那么完全可以做到每次执行时,调用帧只有一项,这将大大节省内存。这就是 “ 尾调用优化 ” 的意义
function f() {
let m = 1;
let n = 2;
return g(m + n);
}
f();
// 等同于
function f() {
return g(3);
}
f();
// 等同于
g(3);
对象扩展
简洁表示法
{
let o = 1
let k = 2
let es5 = {
o: o,
k: k,
say: function () {console.log('hhh')}
}
let es6 = {
o,
k,
say () {console.log('hhh')}
}
console.log(es5)
console.log(es6)
es5.say()
es6.say()
}
属性表达式
{
let a = 'b'
let es5 = {
a: 'c'
}
// [a] 中的a就是'b'
let es6 = {
[a]: 'c'
}
console.log(es5, es6)
}
新增API Object.is 等同于 ===
{
console.log('String', Object.is('abc', 'abc'), 'abc' === 'abc')
console.log('Array', Object.is([], []), [] === [])
console.log('Object', Object.is({}, {}), {} === {})
let arr = []
let arr1 = arr
console.log('Array', Object.is(arr, arr1), arr === arr1)
let obj = {}
let obj1 = obj
console.log('Object', Object.is(obj, obj1), obj === obj1)
}
新增API Object.assign 拷贝
{
console.log(Object.assign({a: 'a'}, {b: 'b'}))
let objA = {a: 'a'}
let objB = {b: 'b'}
console.log(Object.assign(objA, objB))
console.log('objA', objA)
console.log('objB', objB)
}
对象遍历
注意 Array.prototype.entries 、 Object.entries
{
let obj = {
a: 1,
b: 2,
c: 3
}
for (let [key, value] of Object.entries(obj)) {
console.log(key, value)
}
}
扩展运算符
{
let {a, b, ...c} = {
'a': 'test a',
'b': 'test b',
'c': 'test c',
'd': 'test d',
}
console.log(a, b, c) //test a test b { c: 'test c', d: 'test d' }
}