let 和 const 命令
let
let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。
let a = 1;
// 1.不存在变量提升。
let a = 1;
console.log(a); //报错
let a = 1;
// 2.暂时性死区
let a = 1;
{
console.log(a); //报错
let a = 1;
}
// 3.不允许重复声明
let a = 1;
let a = 2; //报错
// 4.只在当前块有效 块级作用域
{
let a = 1;
}
console.log(a);//报错
复制代码const
const命令,声明一个只读的常量。一旦声明,常量的值就不能改变。 本质: 变量指向的那个内存地址不得改动,对于数值,字符串,布尔值来说,值保留在变量指定的内存地址中,而对于对象和数组来说,变量指向的内存地址保存的是一个指针,const 只能保证这个指针是固定的,而指向的数据格式是可变的。
const b = 2;
//1.常量,不允许改变值,只声明不赋值也报错
const b = 2;
const b; // 报错
const b = 3;//报错
b = 3;//报错
//2.不存在变量提升,暂时性死区,只在当前块有效跟let命令一致
复制代码解构赋值
ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。
// 普通的解构赋值
var [a, b, c] = [1, 2, 3];
console.log(a);//a的值为1
console.log(b);//b的值为2
console.log(c);//c的值为3
// 数组 对象 字符串
var [obj,arr,string,number,a=3,b] = [{a:1},[1,2,3,4],'1',2];
var [c,d,f] = '123';
console.log(obj); //{a:1}
console.log(arr); // [1,2,3,4]
console.log(string); //1
console.log(number); //1
console.log(a) //3 允许给默认值
console.log(b); //undefined 不完全解构,值会是undefined
console.log(c); //1
console.log(d); //2
console.log(f); //3
//嵌套解构赋值
var [a,b,[c1,c2]] = [1,2,[3.1,3.2]];
console.log(c1); //3.1
console.log(c2); //3.2
var {a:{b}} = {a:{b:2}};
复制代码字符串扩展
字符串遍历接口
ES6为字符串提供了遍历接口,字符串可以通过 for...of 循环遍历
let str = '123321';
for (let item of str) {
console.log(`item = ${item}`)
}
// item = 1
// item = 2
// item = 3
复制代码另外一些常用的函数扩展
includes():返回布尔值,表示是否找到了参数字符串。第二个参数表示检索的位置let s = 'Hello world!'; console.log(s.includes('o')) // true console.log(s.includes('o',8)) // false 复制代码startsWith():返回布尔值,表示参数字符串是否在原字符串的头部。第二个参数表示检索的位置let s = 'Hello world!'; console.log(s.startsWith('Hello')) // true console.log(s.startsWith('2')) // false console.log(s.startsWith('world',6)) // true 复制代码endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部。第二个参数表示检索的位置,针对 n 前面的字符串let s = 'Hello world!'; console.log(s.endsWith('!')) // true console.log(s.endsWith('o',5)) // true console.log(s.endsWith('2')) // false 复制代码repeat():将目标字符串重复N次,返回一个新的字符串,不影响目标字符串。let s = 'Hello world!'; console.log(s.repeat(3)) // Hello world!Hello world!Hello world! console.log(s) // Hello world! 复制代码pasStart()补全字符串长度的函数,第一个参数指定长度,第二个参数指定补全的字符串,为空则用空格补,从字符串开始补全console.log(s.padStart(20,'x')) // xxxxxxxxHello world! 复制代码pasEnd(),从字符串末尾补全console.log(s.padEnd(20,'x')) // Hello world!xxxxxxxx 复制代码
模板字符串
模板字符串(template string)是增强版的字符串,用反引号(`)标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。
let a = 1;
let b = [1,2,3];
let c = {a};
function aFn(a){
return a;
}
var string = `a=${a},b=[${b.map(bItem => `${bItem}`)}],a+b=${a+b[1]},c=${c.a},d=${aFn(a)}`;
console.log(string); //a=1,b=[1,2,3],a+b=3,c=1,d=1
复制代码数值扩展
Number.isNaN()用来检查一个值是否为NaN,注意:是判断非数值,而不是判断数值,当返回false的时候,不一定就是一个数值,有可能是一个非数值类型的参数。isNaN('abc');//结果:true //'abc'无法转为一个数值,返回true Number.isNaN('abc'); //结果:false //'abc'是字符串,Number.isNaN不做类型转换,直接返回false 复制代码Number.isFinite()用来检查一个数值是否为有限。console.log(Number.isFinite('abc')); //false,不做类型转换,直接返回false console.log(Number.isFinite('123')); //false console.log(Number.isFinite(Infinity)); //true 复制代码Number.isInteger()用来判断一个数值是否为整数。console.log(Number.isInteger(1)) //true console.log(Number.isInteger(1.2)) // false console.log(Number.isInteger('15')) //false console.log(Number.isInteger(true)) //false 复制代码Math.trunc()用于去除一个数的小数部分,返回整数部分。console.log(Math.trunc(1.1)); //1 console.log(Math.trunc(1)); //1 console.log(Math.trunc(-1.1)); //-1 console.log(Math.trunc(-0.1)); // -0 console.log(Math.trunc('-0.a')); // NaN 复制代码Math.sign()用来判断一个数到底是正数、负数、还是零。返回+1,-1,0,NaNconsole.log(Math.sign(+1)) // +1 console.log(Math.sign(-1)) //-1 console.log(Math.sign(0)) // 9 console.log(Math.sign(-0)) // -0 console.log(Math.sign('1')) // +1 console.log(Math.sign(NaN)) // NaN console.log(Math.sign('foo')) // NaN 复制代码Math.cbrt()计算一个数的立方根console.log(Math.cbrt(27)); // 3 console.log(Math.cbrt(-27)); // -3 console.log(Math.cbrt(0)); //0 console.log(Math.cbrt('h')); //NaN 复制代码Math.hypot()返回所有参数的平方和的平方根console.log(Math.hypot(3,4)) // 5 console.log(Math.hypot(3,NaN)) // NaN console.log(Math.hypot(3,'4')) // 5 console.log(Math.hypot(3,'4e')) // NaN 复制代码Math.expm1返回 e^x - 1 即 Math.exp(x) - 1Math.log1p返回 In(1+x) 即 Math.log(1+x)Math.log10返回 10 为底的的 x 的对数Math.log2返回 2 为底的的 x 的对数
函数扩展
函数默认值
ES6允许函数参数定义默认值,可以直接写在参数定义后面 (必须是尾参数),需要注意的是,设定完参数默认值之后,函数的 length 属性会失真,length 属性的含义是该函数预期传入的参数个数,设为默认值之后,就不包括这个参数了,rest 属性也不会计入
function log(x, y = x + "World") {
// 默认值相当于已经被声明了,不能使用let跟const再次声明
// 参数的默认值不是传值,而是每次重新计算的默认值表达式,
// 参数默认值其实是惰性求值
console.log(x, y);
}
log("X"); // X XWorld
log("X", "Y"); // X Y
function foo({x,y=5}){
console.log(`x=${x},y=${y}`);
}
foo({}); //x = undefined y = 5
foo({ x: 5 ,y:10}); // x = 5 y = 10
foo({ x: 5 }); // x = 5 y = 5
复制代码rest参数
rest 参数用于获取函数的多余参数,这样就不需要显性的使用 arguments 对象了 (rest参数之后不能再有其他参数)
function add(...values){
let sum = 0;
values.forEach(item=>sum+= parseInt(item))
console.log(sum);
}
add(1,2,3); // 6
复制代码箭头函数
ES6 增加了箭头函数 =>
// 1.当不需要参数的时候可以用()代替参数部分 ()=>{};
// 2.当只有一个参数的时候,()可以省略,当执行代码只有一行的时候{}可以省略 item=>item*2;
var arr = [1, 2, 3];
arr = arr.map(x => x * x);
console.log(arr);
var numbers = (...nums)=>nums;
var numArr = numbers(1,2,3,4);
console.log(numArr);
复制代码箭头函数和普通函数的区别
- 没有this!!!需要通过 查找作用域链来确定
this的值 ,那些说指向定义时对象的都是错的,箭头函数被非箭头函数包含,this 绑定的就是最近一层非箭头函数的 this。
// 浏览器环境
let bar = {
bar:function(){
console.log(this)
return this
},
foo:()=>{
console.log(this)
return this
},
foo2:function(){
return (()=>{
console.log(this)
return this
})();
}
}
let barFoo = bar.foo;
let barFoo2 = bar.foo2;
bar.bar() // bar
bar.foo() // window
bar.foo2() // bar
barFoo(); //window
barFoo2(); //window
console.log(bar.foo() === barFoo2()); // true
复制代码- 没有
arguments, 因为箭头函数可以访问外围函数的arguments
let bar = {
...
foo2:function(a,b){
return ()=>{
console.log(arguments)
console.log(this)
return this
};
}
}
let barFoo2 = bar.foo2(1,2);
barFoo2();
//arguments{a:1,b:2,length:2}
//bar
复制代码- 不能通过 new 关键字调用,也没有 new.target
- 没有原型,也没有 super
数组扩展
扩展运算符
扩展运算符(spread)是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。
console.log(...[1, 2, 3])// 1 2 3
console.log(1, ...[2, 3, 4], 5)// 1 2 3 4 5
const a1 = [1, 2];
// 写法一
const a2 = [...a1];
console.log(a1);//[1, 2]
console.log(a2);//[1, 2]
复制代码数组扩充方法
Array.from()将类数组对象和可遍历对象转化为真正的数组let arrayLike = { '0': 'a', '1': 'b', '2': 'c', length: 3 } console.log(`Array.from(arrayLike) => ${arr03}`); //Array.from(arrayLike) => ['a','b','c'] 复制代码Array.of()用于将一组值,转换为数组。let arr04 = Array.of(1, 1, 1, 1, 1, 1, 1, 1, 1); console.log(`Array.of(1,1,1,1,1,1,1,1,1) => ${arr04}`);//[1, 1, 1, 1, 1, 1, 1, 1, 1] 复制代码array.copyWithin(target,start,end)在当前数组内部,将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组。- target(必需):从该位置开始替换数据。如果为负值,表示倒数。
- start(可选):从该位置开始读取数据,默认为 0。如果为负值,表示倒数。
- end(可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示倒数。
let a = [1,2,3,4,5]; a.copyWithin(0, 3); console.log(a) //[4,2,3,4,5] 复制代码array.find() array.findIndex()数组实例对象的 find 方法和 findIndex 方法, find 方法是找到符合条件的数组元素,返回数组元素,findIndex 是返回数组下标,接受一个回调函数,第二个参数是可以传入 this 绑定回调函数的 this 对象- 回调函数可以接受三个参数,当前的值,位置,原数组
let arr = [1,2,3,4,5,1,3,2,3] console.log(arr.find((value,index,arr)=>value>2)); //3 console.log(arr.findIndex(value=>value>1)); // 1 复制代码array.fill()给定值填充一个数组,第一个参数是定值,第二个参数是起始位置,第三个参数是结束位置console.log([1,2,3,4].fill('fill')) //[ 'fill', 'fill', 'fill', 'fill' ] console.log([1,2,3,4,5].fill('fill',2,4))//[ 1, 2, 'fill', 'fill', 5 ] 复制代码array.keys() array.values() array.entries()这三个方法返回一个遍历器对象,通过调用 for..of 可以实现循环遍历,keys() 是对键名的遍历,values() 是对键值的遍历,entries() 是对键值对的遍历var arr = [1,2,3]; for( let index of arr.keys()){ console.log(`index-${index}`) } // index-0 index-1 index-2 for( let value of arr.values()){ console.log(`value-${value}`) } // value-1 value-2 value-3 for( let [index,value] of arr.entries()){ console.log(`${index}-${value}`) } // 0-1 1-2 2-3 复制代码array.includes()返回一个布尔值,表示某个数组包含给定的值。
数组的空位
如果数组中存在空位 [,1,]
- forEach() filter() every() some() 会跳过空位
- map() 会跳过空位,但是保留这个值
- join() toString() 会视为 undefined 转为空字符串处理
- from() ... keys() values() entries() 会将空位转为 undefined
- for...of 会遍历空位
对象的扩展
简洁表示法
可以使用变量名简写属性名,直接看吧...也不知道怎么表达好...
let bar = 'foo';
let func = function(){console.log('func')}
let foo = {
bar,
func,
funcIn(){
console.log('funcIn')
}
}
console.log(foo.bar); //foo
foo.func(); // func
foo.funcIn(); // funcIn
复制代码属性名表达式
ES6 允许字面量定义对象时使用表达式
let propKey = 'foo';
let obj = {
[propKey]:1,
[propKey+'1']:1,
}
console.log(obj)//{ foo: 1, foo1: 1 }
复制代码对象扩展方法
Object.is()比较两个值是否严格相等 类似===Object.assign()将源对象 的所有可枚举的属性复制到目标对象中,注意,这个方法是浅复制var target = {a:1}; var source1 = {b:{b:1}}; var source2 = {c:[1,2,3]}; var source3 = {d:'d'}; Object.assign(target,source1,source2,source3) console.log(target);//{ a: 1, b: { b: 1 }, c: [ 1, 2, 3 ], d: 'd' } target.b.b = 2; target.c.push(1); target.d = 'dd'; console.log(target);//{ a: 1, b: { b: 2 }, c: [ 1, 2, 3, 1 ], d: 'dd' } console.log(source1);//{ b: { b: 2 } } console.log(source2);//{ c: [ 1, 2, 3, 1 ] } console.log(source3);//{ d: 'd' } 复制代码
属性遍历
for..of循环遍历对象自身和继承的可枚举属性var target = { a:1, [Symbol('abc')]:'abc' }; Object.defineProperty(target,'b',{ value:'B', enumerable:false }) for (let key in target) { console.log(key) console.log(target[key]) } // a 1 复制代码Object.keys(obj)返回一个数组,包括自己对象自身的所有可枚举属性for (let key of Object.keys(target)) { console.log(key) console.log(target[key]) } // a 1 复制代码Object.getOwnPropertyName(obj)返回一个数组,包括自己对象自身的所有属性for (let key of Object.getOwnPropertyNames(target)) { console.log('getOwnPropertyNames') console.log(key) console.log(target[key]) } // a 1 b B 复制代码Object.getOwnPropertySymbols(obj)返回一个数组,包括自己对象自身所有Symbol属性for (let key of Object.getOwnPropertySymbols(target)) { console.log('getOwnPropertySymbols') console.log(key) console.log(target[key]) } // Symbol(abc) abc 复制代码Reflect.ownKeys(obj)for (let key of Reflect.ownKeys(target)) { console.log('ownKeys') console.log(key) console.log(target[key]) } // a 1 b B Symbol(abc) abc 复制代码
Symbol
ES6新引入的一个原始数据类型 Symbol,表示独一无二的值,是第七种数据类型,Symbol值通过 Symbol 函数生成,本质上是医用类似于字符串的数据类型。
一般可做为对象属性名
let s = Symbol('1');
let v = Symbol('1');
let obj = {
[s]:'s',
[v]:'v',
}
console.log(obj) //{ Symbol(1): 's', Symbol(1): 'v' }
console.log(obj[s]) // 's' 必须要通过这个方式获取,否则获取不到
console.log(typeof s) //Symbol
console.log(s) //Symbol(1)
console.log(v === s) // false
复制代码属性名的遍历
Symbol 作为属性名的时候,不会出现在 for...in for...of 循环中,更不会出现在 Object.keys() Object.getOwnPropertyNames() 返回,但是他并不是私有属性,可以被 Object.getOwnPropertySymbols() 和 Reflect.ownKeys() 方法返回指定所有 Symbol 属性名。
Symbol.for() Symbol.keyFor()
Symbol.for() 可以产生一个值,可供全局环境中搜索,也就是说,Symbol.for('a') 调用 N 次 都会返回同一个 Symbol 值
Symbol.keyFor() 返回对应 Symbol 值的键
let s = Symbol.for('1');
let v = Symbol.for('1');
console.log(v === s) // true
console.log(Symbol.keyFor(s)) // 1
复制代码内置的 Symbol 值
- Symbol.hasInstance 指向一个内部方法,当对象使用 instanceof 的时候调用这个方法。判断该对象是否为某个构造函数的实例。
class Even { static [Symbol.hasInstance](obj){ return Number(obj) % 2 === 0 } } console.log(1 instanceof Even); // true 实际上调用的是 Even[Symbol.hasInstance](1) console.log(2 instanceof Even); // true console.log(1234 instanceof Even); // true 复制代码 - Symbol.isConcatSpreadable 可以通过设置对象属性 Symbol.isConcatSpreadable 的布尔值,表示该数组在 concat 时 是否要展开。
let arr = [3,4]; arr[Symbol.isConcatSpreadable] = false; console.log([1,2].concat(arr,[5,6])) // [ 1, 2, [ 3, 4, [Symbol(Symbol.isConcatSpreadable)]: false ], 5, 6 ] 复制代码 - Symbol.species 对象的 Symbol.species 指向当前对象的构造函数。创建实例的时候会调用这个方法,使用这个属性返回的函数当作构造函数来创造新的实例
- Symbol.match 指向一个函数,当执行 str.match() 时,如果该属性存在,会调用它返回该方法的返回值
- Symbol.replace 指向一个函数,当执行 String.prototype.replace() 时,如果该属性存在,会调用它返回该方法的返回值
- Symbol.search 指向一个函数,当执行 String.prototype.search() 时,如果该属性存在,会调用它返回该方法的返回值
- Symbol.split 指向一个函数,当执行 String.prototype.split() 时,如果该属性存在,会调用它返回该方法的返回值
- Symbol.iterator 指向该对象的默认遍历器方法
- Symbol.toPrimitive 指向一个方法,对象被转为原始类型的值的时候调用该方法,返回该对象对应的原始类型值
let obj = { [Symbol.toPrimitive](hint){ let key; switch (hint) { case 'number': key = 1; break; case 'string': key = '1'; break; case 'default': key = 'default'; break; default: throw new Error() } return key } } console.log(4 - obj); //3 console.log(String(obj)); // 1 console.log(obj == 'default'); //false 复制代码 - Symbol.toStringTag 指向一个方法,对象调用 Object.prototype.toString 方法时,如果此方法存在,返回其返回值
console.log({[Symbol.toStringTag]:'foo'}.toString()) //[object foo] 复制代码 - Symbol.unscopables 指向一个对象,指定了使用 with 关键字时那些属性会被 with 环境擦除
Set 和 Map
Set
Set 是 ES6 提供的新的数据结构,集合中所有的成员都是唯一的,没有重复的成员
Set 本身是一个构造函数,用来生成 Set 数据结构。
属性
- Set.prototype.constructor 构造函数
- Set.prototype.size 成员总数
Set 方法
- add(value) 添加该值,返回 Set 结构
- delete(value) 返回是否删除成功的布尔值,在 Set 中删除该值
- has(value) 返回一个布尔值,表示该值是否是 Set 的成员
- clear() 清除所有成员
var s = new Set([2]);
s.add(1); //Set [ 1, 2 ]
s.add(2); // Set [ 1, 2 ]
s.has(1); // true
s.delete(1); // true
s.clear() // Set []
复制代码Set 遍历方法
- keys() 返回键名的遍历器
- values() 返回键值的遍历器
- entries() 返回键值对的遍历器
- forEach() 返回回调函数遍历每个成员
var s = new Set([1,2,3])
console.log(s.keys()); //SetIterator { 1, 2, 3 }
console.log(s.values()); //SetIterator { 1, 2, 3 }
console.log(s.entries()); //SetIterator { [ 1, 1 ], [ 2, 2 ], [ 3, 3 ] }
s.forEach((value,key)=>{
console.log(`${value}:${key}`)
})
//1:1 2:2 3:3
复制代码WeakSet
WeakSet 结构跟 Set 类似,是不重复值的集合,他们的区别在于
- WeakSet 的成员只能是对象,不能是其他值
- WeakSet 的对象是弱引用,垃圾回收机制不考虑 WeakSet 对该对象的引用,也就是说,外面不在引用该对象,那么垃圾回收机制会自动回收该对象,不会考虑是否在 WeakSet 中。
- 它之存放了对象的引用,它会随着对象的消失而消失,所以其内部成员并不固定,所以规定其不可遍历
WeakSet 属性和方法
WeakSet 方法
- WeakSet.prototype.add(value) 添加该值,返回 WeakSet 结构
- WeakSet.prototype.delete(value) 返回是否删除成功的布尔值,在 WeakSet 中删除该值
- WeakSet.prototype.has(value) 返回一个布尔值,表示该值是否是 WeakSet 的成员
let ws = new WeakSet(); var a = {a:1} var b = {a:1} var c = {a:1} console.log(ws.add(a)) // WeakSet{{a:1}} console.log(ws.add(b)) // WeakSet{{a:1},{a:1}} console.log(ws.add(c)) // WeakSet{{a:1},{a:1},{a:1}} console.log(ws.delete(a))// true console.log(ws.has(a))// false 复制代码
Map
Map 是 ES6 提供的另一种数据结构,它类似于对象,也是键值对的集合,但是这个键值不局限于字符串,各种类型的值都可以当为键,事实上 Map 提供了一种 ‘值-值’ 的对应,是一种更完善的 hash 结构实现
Map 方法
- set() 设置 key 所对应的键值,然后返回 Map 结构
- get() 读取 key 所对应的键值,如果找不到 key 则返回 undefined
- has() 返回一个布尔值,表示某个键是否存在于 Map 数据结构
- delete() 删除某个键,成功返回true,失败返回false
- clear() 清除所有清除所有成员
let m = new Map(); let o = {a:1}; m.set(o,'value'); //Map { {a:1} => 'value' } m.get(o); // 'value' m.has(o); // true m.size; // 1 m.delete(o); //true m.clear(); // Map {} 复制代码
Map 遍历
- keys() 返回键名的遍历器
- values() 返回键值的遍历器
- entries() 返回键值对的遍历器
- forEach() 返回回调函数遍历每个成员
console.log(m.keys()); //MapIterator { {} }
console.log(m.values()); //MapIterator { 'value' }
console.log(m.entries()); //MapIterator { {} => 'value' }
m.forEach((value,key)=>{
console.log(`${value}:${key}`)
})
// value:[object Object]
复制代码Map 转换为数组
console.log([...m]) //[ [ { a: 1 }, 'value' ] ]
数组转换为 Map
console.log(new Map([[true,1],[{foo:1},1]])) //Map { true => 1, { foo: 1 } => 1 }
Map 转换为对象
var oM = new Map();
oM.set('yes',true)
oM.set('no',false)
console.log(oM);
function strMapToObj(strMap){
let obj = {};
for (let [k,v] of strMap) {
obj[k] = v
}
return obj
}
console.log(strMapToObj(oM)) //{ yes: true, no: false }
复制代码对象转换为 Map
function strObjToMap(obj){
let map = new Map();
for (let k of Object.keys(obj)) {
map.set(k,obj[k]);
}
return map
}
console.log(strObjToMap({yes:true,no:false})) //Map { 'yes' => true, 'no' => false }
复制代码WeakMap
WeakMap 跟 Map 结构类似 也用于生成键值对的集合,区别在于
- WeakMap 只接受对象作为键名,不接受其他类型的值作为键名
- WeakMap 跟 WaekSet 类似,是弱引用,不计入垃圾回收机制,有助于防止内存泄漏,同样也没有遍历操作,也没有 size 属性
WeakMap方法
- WeakMap.prototype.set(key,value) 添加该值,返回 WeakMap 结构
- WeakMap.prototype.get(key) 添加该值,返回 WeakMap 结构
- WeakMap.prototype.delete(key) 返回是否删除成功的布尔值,在 WeakMap 中删除该值
- WeakMap.prototype.has(key) 返回一个布尔值,表示该值是否是 WeakMap 的成员
let ws = new WeakMap(); var a = {a:1}; var b = {b:1}; console.log(ws.set(a,1))// WeakMap {{…} => 1} console.log(ws.set(b,2))// WeakMap {{…} => 1, {…} => 2} console.log(ws.get(a)) 1 console.log(ws.has(a)) //true console.log(ws.delete(a)) //true console.log(ws)// WeakMap {{…} => 2} 复制代码
4425

被折叠的 条评论
为什么被折叠?



