为什么我们可以在方法 map() 的用法中省略 return 语句

Why can we omit a return statement in this usage of the method map()

当我注意到他们在使用 map() 之后使用 forEach 时,我目前正在查看他们 docs 上的 WebRTC 教程。为了使用 forEach 并期望一个值而不是未定义的数组,map() 需要 return 一个数组,我不知道它是怎么做到的,因为它没有 return 任何东西.

function updateCameraList(cameras) {
    const listElement = document.querySelector('select#availableCameras');
    listElement.innerHTML = '';
    cameras.map(camera => {
        const cameraOption = document.createElement('option');
        cameraOption.label = camera.label;
        cameraOption.value = camera.deviceId;
    }).forEach(cameraOption => listElement.add(cameraOption));
}

由于地图 returns 什么都没有,代码将无法运行。

这是另一种方法

function updateCameraList(cameras) {
  document.getElementById('availableCameras').innerHTML = cameras
  .map(({label, deviceId}) => `<option value="${deviceId}">${label}</option>`)
  .join(""); 
}

我今天了解到我们现在可以使用标签而不是文本

https://jsfiddle.net/mplungjan/osyLzqk2/

这是一个更安全的版本,因为 XSS 的可能性很小

function updateCameraList(cameras) {
  const sel = document.getElementById('availableCameras')
  cameras.forEach(({label, deviceId}) => {
    const option = new Option(label,deviceId); 
    sel.add(option)
  })
}

这是一个无效的 XSS 尝试 - 至少它在 Chrome

中什么都不做

const cameras = [{ deviceId : `xss"></option></select><img src="x" onerror="alert(1)" />`  , label:"bla" }]

    function updateCameraList(cameras) { 
      const xssString = cameras
      .map(({label, deviceId}) => `<option value="${deviceId}">${label}</option>`)
      .join("")
      console.log(xssString)
      document.getElementById('availableCameras').innerHTML = xssString; 
    }


updateCameraList(cameras)
<select id="availableCameras"></select>

代码明显少了一行。代码应该将 undefined 推入一个数组,并将附加到 select.

function updateCameraList(cameras) {
    const listElement = document.querySelector('select#availableCameras');
    listElement.innerHTML = '';
    cameras.map(camera => {
        const cameraOption = document.createElement('option');
        cameraOption.label = camera.label;
        cameraOption.value = camera.deviceId;
        return cameraOption;
    }).forEach(cameraOption => listElement.add(cameraOption));
}

现在我们为什么要循环两次,这有点浪费时间。所以我只循环一次。

function updateCameraList(cameras) {
    const listElement = document.querySelector('select#availableCameras');
    listElement.innerHTML = '';
    cameras.forEach(camera => {
      const cameraOption = document.createElement('option');
      cameraOption.label = camera.label;
      cameraOption.value = camera.deviceId;
      listElement.add(cameraOption));
    });
}