Proxy代理与数组的遍历方法

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。

数组遍历方法

  1. map: 遍历数组,将数组中的每一项都执行一次回调函数,返回一个新的数组
  2. filter: 遍历数组,将数组中满足条件的那些项保留到新数组,并返回新数组
  3. reduce: 接受两个参数,第一个是回调,第二个是回调中的第一个参数,遍历数组,将每次返回的值作为下一次回调的第一个参数
  4. 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等。

相关推荐
Mintopia6 分钟前
Three.js 在数字孪生中的应用场景教学
前端·javascript·three.js
da-peng-song10 分钟前
ArcGIS arcpy代码工具——根据属性结构表创建shape图层
javascript·python·arcgis
夕水22 分钟前
自动化按需导入组件库的工具rust版本完成开源了
前端·rust·trae
不爱总结的麦穗1 小时前
面试常问!Spring七种事务传播行为一文通关
后端·spring·面试
JarvanMo1 小时前
借助FlutterFire CLI实现Flutter与Firebase的多环境配置
前端·flutter
牛马baby1 小时前
Java高频面试之并发编程-11
java·开发语言·面试
Jedi Hongbin1 小时前
echarts自定义图表--仪表盘
前端·javascript·echarts
凯哥19702 小时前
Sciter.js指南 - 桌面GUI开发时使用第三方模块
前端