ES6
一、let const
- let 声明的变量只在代码块内有效
- for循环的计数器适合用let命令
- 不存在变量提升。–即var变量在声明之前就能使用,值为undefine。let不允许
- 暂时性死区
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}
ES6明确规定,如果区块中存在let和const命令,这个区块对这些命令生命的变量,
从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
在代码块内,使用let命令声明变量之前,变量都是不可用的,成为“暂时性死区(TDZ)”。
- 不允许重复声明
不允许在相同作用域内重复声明同一变量
// 报错
function font(){
let a = 10;
var a = 10;
}
// 报错
function func(){
let a = 10;
let a = 1;
}
不能再函数内部重新生命参数
function func(arg){
let arg; //报错
}
function func(arg){
{
let arg; //不报错
}
}
块级作用域
防止外层代码收内层代码的影响
用来计数的循环变量泄露为全局变量
var s = 'hello';
for (var i = 0; i < s.length; i++) {
console.log(s[i]);
}
console.log(i); // 5
- 外层代码块不受内层代码块的影响
function f1() {
let n = 5;
if (true) {
let n = 10;
}
console.log(n); // 5
}
- ES6 允许块级作用域的任意嵌套
{{{{{ let insane = 'Hello World' }}}}};
- 内层作用域可以定义外层作用域的同名变量
{{{{
let insane = 'Hello World';
{let insane = 'Hello World'}
}}}};
const
- 只读常量。一旦声明,常量值不能再改变。
- 声明的同时必须赋值
- 只在块级作用域内有效
- 不存在变量提升
- 暂时性死区
const PI = 3.1415;
console.log(PI) //3.1415
二、解构赋值
规则:只要等号右边不是对象或数组,就将其转为对象。
- 数组的解构赋值
let a = 1;
let b = 2;
let c = 3;
等同于==》
ES6:
let [a,b,c] = [1,2,3]
let [a, [b], d] = [1, [2, 3], 4];
a // 1
b // 2
d // 4
- 允许使用默认值
let [x = 1, y = x] = []; // x=1; y=1
let [x = 1, y = x] = [2]; // x=2; y=2
let [x = 1, y = x] = [1, 2]; // x=1; y=2
let [x = y, y = 1] = []; // ReferenceError: y is not defined
- 变量的解构赋值
- 对象的属性没有次序,变量名需与属性同名。
let { bar, foo } = { foo: "aaa", bar: "bbb" };
foo // "aaa"
bar // "bbb"
let { baz } = { foo: "aaa", bar: "bbb" };
baz // undefined
- 不同名的写法:
let obj = { first: 'hello', last: 'world' };
let { first: f, last: l } = obj;
f // 'hello'
l // 'world'
简写原方法:let { foo: foo, bar: bar } = { foo: "aaa", bar: "bbb" };
- 字符串解构赋值
- 字符串也可以解构赋值,字符串被转换成了一个类似数组的对象
const [a,b,c,d,e] = 'hello';
a // "h"
b // "e"
c // "l"
- 类似数组的对象都有
length
属性
let {length:len} = 'hello'
len //5
- 数值和布尔值的解构赋值
- 等号右边数值和布尔值,会转为对象
let {toString: s} = 123;
s === Number.prototype.toString // true
let {toString: s} = true;
s === Boolean.prototype.toString // true
- undefined 和 null 无法转为对象,所以会报错
let {prop:x} = undefined;
let {prop:y} = null;
- 参数 解构赋值
function add([x, y]){
return x + y;
}
add([1, 2]); // 3
[[1, 2], [3, 4]].map(([a, b]) => a + b);
// [ 3, 7 ]
map是把一个数组的元素经过处理,映射到新的数组中
- 用途
- 提取json数据
let jsonData = {
id: 42,
status: "OK",
data: [867, 5309]
};
let { id, status, data: number } = jsonData;
console.log(id, status, number);
// 42, "OK", [867, 5309]
- 遍历map结构
获取键名和键值方便
const map = new Map();
map.set('first','hello');
map.set('second','world');
for(let [key,value] of map){
console.log(key + 'is' + value)
}
// first is hello
// second is world
//获取键名
for (let [key] of map) {
// ...
}
// 获取键值
for (let [,value] of map) {
// ...
}
三、字符串的扩展
字符串的Unicode表示
- javascript允许采用
\uxxxx
形式表示一个字符,其中xxxx
是Unicode码点
var str = "\uD842"
// 输出 "�"
str2 = "\uD842\uDFB7"
// "��"
- 种表示法只限于码点在\u0000~\uFFFF之间的字符。超出这个范围的字符,必须用两个双字节的形式表示
ES6写法:放在大括号中==>
"\u{20BB7}"
// "��"
"\u{41}\u{42}\u{43}"
// "ABC"
let hello = 123;
hell\u{6F} // 123
- String.fromCodePoint()
可以识别大于0xFFFF的字符
String.fromCodePoint(0x20BB7)
// "��"
String.fromCodePoint(0x78, 0x1f680, 0x79) === 'x\uD83D\uDE80y'
// true
- 字符串的遍历器接口
添加了遍历器接口,使得字符串可以被for…of循环遍历
for (let codePoint of 'foo') {
console.log(codePoint)
}
// "f"
// "o"
// "o"
- includes(),startsWith(),endsWith()
- includes(): 布尔值。是否包含该字符串
- srtartsWith():布尔值。是否在原字符串的头部
- endsWith():布尔值。是都在原字符串的尾部
let s = 'Hello world!';
s.startsWith('Hello') // true
s.endsWith('!') // true
s.includes('o') // true
支持第二参数,表示开始搜索的位置
let s = 'Hello world!';
s.startsWith('world', 6) // true
s.endsWith('Hello', 5) // true
s.includes('Hello', 6) // false
- repeat()
返回一个新字符串,表示将元字符串重复n次
'x'.repeat(3) // "xxx"
'hello'.repeat(2) // "hellohello"
'na'.repeat(0) // ""
参数如果是小数,取整
'na'.repeat(2.9) // "nana"
如果repeat的参数是负数或者Infinity,会报错。
参数是 0 到-1 之间的小数,则等同于0。repeat视同为 0.
NAN
等同于0。
参数为字符串,会嫌转成数字。
'na'.repeat(-0.9) // ""
'na'.repeat(NaN) // ""
'na'.repeat('na') // ""
'na'.repeat('3') // "nanana"
- padStart(),padEnd()
ES2017引入了字符串补全长度的功能。如果某个字符串不够指定长度,会在头部或尾部补全。padStart()用于头部补全,padEnd()用于尾部补全。
'x'.padStart(10,'qw')
"qwqwqwqwqx"
如果原字符串的长度,等于或大于指定的最小长度,则返回原字符串。
扫描二维码关注公众号,回复: 3012607 查看本文章
'xxx'.padStart(2, 'ab') // 'xxx'
'xxx'.padEnd(2, 'ab') // 'xxx'
如果省略第二个参数,默认使用空格补全长度。
'abc'.padStart(10, '0123456789')
// '0123456abc'
'x'.padStart(4) // ' x'
'x'.padEnd(4) // 'x '
常见:数值、格式
'1'.padStart(10, '0') // "0000000001"
'12'.padStart(10, '0') // "0000000012"
'123456'.padStart(10, '0') // "0000123456"
'12'.padStart(10, 'YYYY-MM-DD') // "YYYY-MM-12"
'09-12'.padStart(10, 'YYYY-MM-DD') // "YYYY-09-12"
matchAll()
返回一个正则表达式在当前字符串的所有匹配模板字符串
var html = `this is ${v.item}`;
使用反引号时:
let greeting = `\`Yo\`;
输出 greeting: "`Yo` World!"
变量名放在
${}
中大括号内可以放入任意js表达式进行运算。可以引入对象属性。可以调用函数
`${x}+${y}=${x+y}` // 1 + 2 = 3
let obj = {x: 1, y: 2};
`${obj.x + obj.y}`
// "3"
`foo ${fn()} bar`
`Hello ${'World'}` // "Hello World"
引用方法
// 写法一
let str = 'return ' + '`Hello ${name}!`';
let func = new Function('name', str);
func('Jack') // "Hello Jack!"
// 写法二
let str = '(name) => `Hello ${name}!`';
let func = eval.call(null, str);
func('Jack') // "Hello Jack!"
- 标签模板
跟在函数名后面,该函数江北调用来处理这个模板字符串
alert`123` 等同于==> alert(123)
function tag(stringArr,val1,val2){
// ...
}
// 等同于
function tag(stringArr,...val){
// ...
}
四、正则的扩展
- 字符串对象的四种正则方法:
- match()
- replace()
- search()
- split()
五、数值的扩展
+
- Number.isfinite() //检查一个数值是否为有限的
- Number.isNaN() //检查一个数值是否为NaN
全局方法parseInt()和parseFloat(),移植到Number对象上面,行为完全保持不变。
- Number.parseInt() //把字符串转换成整形
- Number.parseInt() // 字符串转为 浮点数
判断是否为整数
- Number.isInteger()
Number.isInteger(25) // true Number.isInteger(25.0) // true Number.isInteger(25.1) // false Number.isInteger('25') // false
- Number.isInteger()
Number.EPSILON ??
- 安全整数和 Number.isSafeInteger ??
Math对象的扩展
Math.trunc() 去除一个数的小数部分,返回整数部分
Math.trunc(4.9) // 4 Math.trunc(-4.1) // -4 Math.trunc(-4.9) // -4
Math.sign() 用来判断一个数到底是正数、负数、还是零。对于非数值,会先将其转换为数值。
- 参数为正数,返回+1;
- 参数为负数,返回-1;
- 参数为 0,返回0;
- 参数为-0,返回-0;
- 其他值,返回NaN。
Math.cbrt() 计算一个数的立方根。
Math.cbrt(1) // 1 Math.cbrt(2) // 1.2599210498948734 Math.cbrt('8') // 2
Math.clz32() 返回一个数的 32 位无符号整数形式有多少个前导 0。
Math.clz32(0) // 32 Math.clz32(1) // 31 Math.clz32(1000) // 22 Math.clz32(0b01000000000000000000000000000000) // 1 Math.clz32(0b00100000000000000000000000000000) // 2
Math.imul() 返回两个数以 32 位带符号整数形式相乘的结果,返回的也是一个 32 位的带符号整数。
Math.imul(2, 4) // 8 Math.imul(-1, 8) // -8 Math.imul(-2, -2) // 4
Math.fround() 返回一个数的32位单精度浮点数形式。
Math.hypot(3, 4); // 5 Math.hypot(3, 4, 5); // 7.0710678118654755 Math.hypot(); // 0
Math.hypot() 返回所有参数的平方和的平方根
Math.hypot(3, 4); // 5 Math.hypot(3, 4, 5); // 7.0710678118654755 Math.hypot(); // 0
对数方法
- Math.expm1()
- Math.log1p() 自然对数
- Math.log10() 以10为底的对数
- Math.log2() 以2为底的对数
- 双曲对数 若干···
指数运算符 **
- Integer 数据类型
- 运算
六、函数的扩展
- 允许为函数的参数直接设置默认值
function log(x,y = 'hello'){
console.log(x,y)
}
- 参数默认值的位置,应是尾参数。
function f(x = 1, y) {
return [x, y];
}
f() // [1, undefined]
f(2) // [2, undefined])
f(, 1) // 报错
- 函数的length属性。参数的个数
- 指定了默认值以后,函数的length属性,将返回没有指定默认值的参数个数
(function (a) {}).length // 1
(function (a = 5) {}).length // 0
(function (a, b, c = 5) {}).length // 2
- rest参数 (形式为
...变量名
)
- 只能是最后一个参数用rest参数。
- 用于获取函数的多余参数,不需要使用arguments对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。
function add(...values) {
let sum = 0;
for (var val of values) {
sum += val;
}
return sum;
}
add(2, 5, 3) // 10
name属性
返回该函数的函数名
var fa = function abc(){};
fa.name // "abc"
5.箭头函数 =>
var sum = (num1, num2) => num1 + num2;
// 等同于
var sum = function(num1, num2) {
return num1 + num2;
};
尾调用: 指某个函数的最后一步是调用另一个函数
- 尾调用不一定出现在函数尾部,只要是最后一步操作即可
function f(x) { if (x > 0) { return m(x) } return n(x); } 此例中m和n都属于尾调用,因为他们都是函数的最后一步操作
- 尾调用不一定出现在函数尾部,只要是最后一步操作即可
尾递归
数组的扩展
- 1.扩展运算符
- 三个点(
...
)
- 三个点(
console.log(...[1, 2, 3])
// 1 2 3
console.log(1, ...[2, 3, 4], 5)
// 1 2 3 4 5
[...document.querySelectorAll('div')]
// [<div>, <div>, <div>]
- 2.Array.from() 将类似数组的对象和可遍历的对象转为真正的数组
3.Array.of() 将一组值,转换为数组
5.find()和findIndex() 找出第一个符合条件的数组成员。
- 所有数组成员依次执行该回调函数,直到找出第一个函数值为true的成员,返回该成员。若没有,返回undefined
[1, 4, -5, 10].find((n) => n < 0) //5
- 所有数组成员依次执行该回调函数,直到找出第一个函数值为true的成员,返回该成员。若没有,返回undefined
6.fill() 使用给定值,填充一个数组。
['a','b','c'].fill(7) // [7,7,7]
接受第二个第三个参数,用于指定填充的起始位置和结束位置
['a','b','c'].fill(7,1,2) // ['a',7,'c']
- 7.entries(),keys(),values() 遍历数组
用for…of循环遍历,区别 - keys() 对键名的遍历
- values() 对键值的遍历
- entries() 对键值对的遍历
- 7.entries(),keys(),values() 遍历数组
for (let index of ['a', 'b'].keys()) {
console.log(index);
}
// 0 1
for (let elem of ['a', 'b'].values()) {
console.log(elem);
}
// 'a' 'b'
for (let [index, elem] of ['a', 'b'].entries()) {
console.log(index, elem);
}
// 0 "a" 1 "b"
- 8.includes() 返回布尔值
对象的扩展
- Object.keys() Object.values() Object.entries()
- Object.keys,返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历属性的键名。
- Object.values,返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历属性的键值。
- Object.entries,返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历属性的键值对数组。
let {keys, values, entries} = Object;
let obj = { a: 1, b: 2, c: 3 };
for (let key of keys(obj)) {
console.log(key); // 'a', 'b', 'c'
}
for (let value of values(obj)) {
console.log(value); // 1, 2, 3
}
for (let [key, value] of entries(obj)) {
console.log([key, value]); // ['a', 1], ['b', 2], ['c', 3]
}
ES7 ECMAscript2016 新特性:includes 指数操作符(冥运算)
includes:
- arr.includes(str1);
判断是否包含一个指定的值,是为true,否则为false; - arr.includes(searchel,fromindex)
从索引处开始查找指定的值,如果为负值,按照从后往前 arr.length + fromindex的位置开始搜索,默认为0。 - 当fromindex大于等于数组长度,则返回false。该数组不会被搜索
- 当fromindex为负值,极速出的索引将所谓开始搜索指定值的位置。若果计算出的索引小于0,整个数组会被搜索
- 作为一个通用方法。可用于列数组对象。在函数的参数对象上调用includes方法。
var arr = [1,2,3]
arr.includes('2','-1') // false
arr.includes('2','-2') // true
(function(){
console.log([].includes.call(arguments,'a')); // true
console.log([].includes.call(arguments,'d')); // false
})('a','b','c');
includes 兼容性:IE11. IE低版本不支持
对比 indexOf 全兼容
let arr = [4,5,6];
if(arr.indexOf(5) !== -1){
console.log('5 存在')
}
指数操作 冥运算
- ES7 幂指数操作 **
console.log(7**3); //343
- 原方法:
function mi(base,num){
if(num === 1){
return base;
}else{
return base * mi(base,num - 1);
}
}
mi(7,3) // 输出343