proxy
proxy 代理是es6新增的一个特性,用来代理对象,代理对象上的读取,设置,函数调用等13种行为,vue3 主要依靠proxy实现响应式。
语法:
js
const proxyObj = new Proxy(obj, {
// target: 表示被代理的原对象,也就是 obj
// key:要获取的对象上的属性
// receiver:proxy对象的本身
get: function (target, key, receiver) { // 代理对象被访问时触发
return target[key]
},
set: function (target, key, value, receiver) { // 对代理对象上的属性操作时触发
target[key] = value
}
})
也就是对于原对象 obj 的操作全部转为对这个new出来的 Proxy 对象操作。这样就可以更好地根据值的变化来进行相应的操作。
举个例子:
js
const obj = {
name: '张三',
age: 15
}
const girlFriend = () => {
console.log('ok我来了');
}
想让张三到达18岁时,女朋友函数自动触发,如下;
js
<body>
<button id="btn">age++</button>
<script>
const obj = {
name: '张三',
age: 15
}
const girlFriend = () => {
console.log('ok我来了');
}
const btn = document.getElementById('btn');
const proxyObj = new Proxy(obj, {
get: function (target, key, receiver) {
return target[key]
},
set: function (target, key, value, receiver) {
target[key] = value
if (value >= 18) { // 当张三的age>=18时
girlFriend()
}
}
})
btn.addEventListener('click', () => {
proxyObj.age++ // 走 set 函数
console.log(proxyObj.age) // 走 get 函数
})
</script>
</body>
vue3 中的响应式主要就是靠proxy来实现的。就可以在set函数中判断该值是否改变,改变则触发视图更新。如下;
js
const updateView = () => {
console.log('视图更新');
}
const btn = document.getElementById('btn');
const proxyObj = new Proxy(obj, {
set: function (target, key, value, receiver) {
if (value !== target[key]) { // 判断该值是否有变化
target[key] = value
updateView()
}
}
})
btn.addEventListener('click', () => {
proxyObj.age++
})
Reflect
- 新版本的 Object, 将来会打造在Object上面的方法加到reflect上面去
- 相比于传统的 Object 错误的处理机制更加优雅(传错参数时会返回false)
js
const proxyObj = new Proxy(obj, {
get: function (target, key, receiver) {
return Reflect.get(target, key, receiver)
},
set: function (target, key, value, receiver) {
if (value !== target[key]) {
return Reflect.set(target, key, receiver)
updateView()
}
}
})
将参数直接给Reflect就会自动设置好。当参数传错时,会返回false。
数组遍历方法
- map: 遍历数组,将数组中的每一项都执行一次回调函数,返回一个新的数组
- filter: 遍历数组,将数组中满足条件的那些项保留到新数组,并返回新数组
- reduce: 接受两个参数,第一个是回调,第二个是回调中的第一个参数,遍历数组,将每次返回的值作为下一次回调的第一个参数
- forEach: 无法使用传统的控制语句(break, return)来终止循环
语法如下:
map
js
// map
let arr = [1, 2, 3, 4, 5, 6]
const res = arr.map((item, index, arr) => { // 值 下标 数组
return item * 2;
})
console.log(res); // [ 2, 4, 6, 8, 10, 12 ]
filter(过滤)
js
// filter
let arr = [1, 2, 3, 4, 5, 6]
const res = arr.filter((item, index, arr) => {
return item > 2
})
console.log(res); // [ 3, 4, 5, 6 ]
reduce
js
// reduce
let arr = [1, 2, 3, 4, 5, 6]
const res = arr.reduce((prev, cur, index, arr) => {
console.log(prev, cur, index, arr);
}, 0)
console.log(res);
reduce接收两个参数,第一个参数是回调,回调里面接收四个参数(prev, cur, index, arr)
分别为prev表示该reduce上一次循环return出来的值,cur表示当前值,index,arr分别表示下标,数组,而第二个参数就是第一次循环时prev的值。
js
let arr = [1, 2, 3, 4, 5, 6]
const res = arr.reduce((prev, cur, index, arr) => {
console.log(prev, cur, index, arr);
return 9
}, 0)
console.log(res); // 9
通常使用reduce来做数组的累加,如下
js
let arr = [1, 2, 3, 4, 5, 6]
const res = arr.reduce((prev, cur, index, arr) => {
console.log(prev, cur, index, arr);
// 0 1 0[1, 2, 3, 4, 5, 6]
// 1 2 1[1, 2, 3, 4, 5, 6]
// 3 3 2[1, 2, 3, 4, 5, 6]
// 6 4 3[1, 2, 3, 4, 5, 6]
// 10 5 4[1, 2, 3, 4, 5, 6]
// 15 6 5[1, 2, 3, 4, 5, 6]
return prev + cur
}, 0)
console.log(res); // 21 通常用于数组的累加
forEach
这个是js中最早用来遍历数组的方法,但是有个特殊的地方,就是无法使用传统的控制语句(break, return)来终止循环。
如下;
js
let arr = [1, 2, 3, 4, 5, 6]
arr.forEach((item, index, arr) => {
if (item === 3) {
return
}
console.log(item); // 1 2 4 5 6 也就是return 或 break无法终止掉循环,还会接着循环
})
面试官:那么如何终止循环呢?
可以使用 try catch 错误捕获机制;
js
let arr = [1, 2, 3, 4, 5, 6]
try {
arr.forEach((item, index, arr) => {
if (item === 3) {
throw new Error('循环终止')
}
console.log(item);
})
} catch {
console.log('循环终止');
}
不会导致程序崩溃。输出如下:
for...of 可以平替上面的forEach方法,且可以使用(break,return)来终止循环。
js
let arr = [1, 2, 3, 4, 5, 6]
for (let item of arr) {
if (item === 3) {
break
}
console.log(item); // 1 2
}
es6 新增的方法
let const 变量,数组,对象解构赋值,对于常见的字符串,数字,数组,函数,对象新增加了一些方法,Symbol,Set和Map数据结构,Proxy,Reflect,Promise对象,Iterator迭代器,for...of ,Generator,async/await,class等。