你不知道的Javascript-下 ES6
》》语法
块级作用域
let、const解决问题 变量提升(旧版解决变量提升,使用立即执行函数)
const(值类型,对象类型)
没有深度只读,需要遍历设置Object.freeze()
手写,需进行类型判断和递归
展开、收集运算符...
展开数组:拼合数组 let arr = [...arr1, ...arr2, ...arr3]
收集数组-函数参数收集:收集多余参数至数组 function testFunc(a, b, c, ...d){ console.log(d.length) }
展开对象:合并对象 let obj = {...obj1, ...obj2}
收集对象:let {aaa, ...ccc} = {a: 100, b: 'gpf', c: 123} ccc:{b: 'gpf', c: 123}
默认值参数
函数默认值(替代原有写法 let yy = params1 || 'initData'),解构输出值的默认值
解构-简洁赋值(可设置默认值,用于构造数据)
数组解构(对位) let [a, b=1222, c, d=100]=[1,2,3] =====> 1 2 3 100
对象解构(相同key对应)---支持深层嵌套和取重复的键(下文的o2.x和yyy都可取到a的值)
另外的活用:
var o1 = { a: 1, b: 2, c: 3 },
o2 = {};
( { a: o2.x, b: o2.y, c: o2.z, a: yyy } = o1 );
解构注意事项:(解构可能污染作用域,另外解构的数据是浅拷贝,会互相影响)
对象字面量扩展
属性(键值一样可缩写)
方法可省略function(getData(){})
模版字面量``(可插值和解析表达式)
箭头函数
特征:改变this指向,父级作用域;简洁。
典型不适用场景:
dom1.addEventListener('resize', ()=>{
// 此时this指向的不是预期的监听dom对象,而是全局对象
})
let obj = {name: 'gpf', getName()=>{}}
obj.getName() this取得的是外部对象,而不是对象实例本身
箭头函数不能取到参数列表:arguments
》》代码组织
迭代器(一个用于消耗的数据结构,借助迭代器接口) 迭代器操作对象:数组(js中的nodeList--数据结构)、set/map集合(类数组对象)、字符串(对象类型不行) 自定义迭代器:实现其[Symbol.iterator]接口
// 一、小例-数组转为迭代器
var arr = [1,2,3];
var it = arr[Symbol.iterator]();
it.next();
// 二、样例-自定义迭代器(斐波那契数列)
var Fib = {
[Symbol.iterator]() {
var n1 = 1, n2 = 1;
return {
// 使迭代器成为iterable
[Symbol.iterator]() { return this; },
next() {
var current = n2;
n2 = n1;
n1 = n1 + current;
return { value: current, done: false };
},
return(v) {
console.log(
"Fibonacci sequence abandoned."
);
return { value: v, done: true };
}
};
}
};
for (var v of Fib) {
console.log( v );
if (v > 50) break;
}
// 三、流控-迭代器的流控
var tasks = {
[Symbol.iterator]() {
var steps = this.actions.slice();
return {
// 使迭代器成为iterable
[Symbol.iterator]() { return this; },
next(...args) {
if (steps.length > 0) {
let res = steps.shift()( ...args );
return { value: res, done: false };
}
else {
return { done: true }
}
},
return(v) {
steps.length = 0;
return { value: v, done: true };
}
};
},
actions: []
};
tasks.actions.push(
function step1(x){
console.log( "step 1:", x );
return x * 2;
},
function step2(x,y){
console.log( "step 2:", x, y );
return x + (y * 2);
},
function step3(x,y,z){
console.log( "step 3:", x, y, z );
return (x * y) + z;
}
)
var it = tasks[Symbol.iterator]();
it.next( 10 ); // step 1: 10
// { value: 20, done: false }
it.next( 20, 50 ); // step 2: 20 50
// { value: 120, done: false }
it.next( 20, 50, 120 ); // step 3: 20 50 120
// { value: 1120, done: false }
it.next(); // { done: true }
生成器(用于阻塞流控)
function *gen(){
console.log('生成器 函数')
yield console.log(1)
yield console.log(2)
yield console.log(3)
return console.log(4)
}
斐波那契数列的生成器函数
function* fibs() {
let a = 0;
let b = 1;
while (true) {
yield a;
[a, b] = [b, a + b];
}
}
let [first, second, third, fourth, fifth, sixth,a,b,c,d,e] = fibs();
可以方便的解构:a = 8;d= 34
模块(esm)
import {api1, api2} from './js.js' 按需导入导出
类(扩展基础类的功能extend:class MyCoolArray extends Array , Error 扩展数组、扩展错误基类)
异步流控
promise(为异步操作提供稳定性、有序性、可预测性)
promise+生成器(完成流控) 有点类似async、await
集合
set、map(注意操作api的不同)
新增api
Array
初始化转化类
from类数组转化为数组
of创建空数组
falt按层级扁平化多维数组
查询遍历类
indexOf(严格匹配,返回下标)类比find(自定义匹配方法,返回匹配元素),findIndex则可完全代替indexOf
也类似some 但这种方式的缺点是如果找到匹配的值的时候,只能得到匹配的 true/false 指示,而无法得到真正的匹配值本身。
filter(匹配的数组组织返回)
map、reduce
some、every《《《 foreach(不能中断return循环)
Object,
Number
元编程
Proxy(返回一个Proxy对象包裹的响应式对象,是Object.defineProperty的升级版,恰恰可以用于vue3的响应式)
let person = {name: 'gpf', age: 100}
const p = new Proxy(person, {
get(obj, property){
// 无明确指定属性
console.log('get property: '+ property)
return obj.property
},
// 修改或者新增属性
set(obj, property, val){
if (property === 'age') {
if (!Number.isInteger(val)) {
throw new TypeError('The age is not an integer');
}
if (val > 200) {
throw new RangeError('The age seems invalid');
}
}
// 属性值修改,进行页面更新渲染操作
obj[property] = val
console.log('修改了obj对象的property属性,修改值为val')
},
deleteProperty(target, propName){
console.log('删除属性需要,自己去实现下,相当于封装了自己的元操作')
return delete target[propName]
}
})
console.log(p)
p.name // 进行get逻辑,因为p成为Proxy代理对象
person.name // 不进行操作get逻辑
Reflect