为什么在单独使用map时使用map.call会做同样的事情?

时间:2017-07-24 15:37:30

标签: javascript

这就是问题:

  

编写一个以ROT13编码的字符串作为输入的函数   返回一个已解码的字符串。

我已经解决了。我正在查看给定的解决方案 - 其中一个使用.map.call,如下所示:

function rot13(str) {
  return str.split('')
    .map.call(str, function(char) {
      x = char.charCodeAt(0);
      if (x < 65 || x > 90) {
        return String.fromCharCode(x); 
      }
      else if (x < 78) {
        return String.fromCharCode(x + 13);
      }
      return String.fromCharCode(x - 13);
    }).join('');  
}

我不明白为什么在使用.map.call(str, function(char)时使用.map(function(char)会做同样的事情?我的意思是我尝试了它,只是删除了.call位on repl,它给出了相同的结果。或者我可能不清楚.call是如何工作的。我已经阅读了关于它的MDN文章,但仍然不确定它是如何工作的。或者为什么要使用它。

2 个答案:

答案 0 :(得分:2)

如果要指定对象call应该指向,则需要调用this。以这种方式使用数组函数主要是在有问题的对象不是数组时(因此没有obj.map)但可以被视为数组(如字符串或HTMLCollection)。因此,可以调用[].map.call(obj, callback)obj是应该调用地图的对象。

正如您所注意到的那样,在这里使用它的方式不必要地复杂化。只需拨打[].map.call(str, ...str.split('').map(...即可。

顺便说一下:return String.fromCharCode(x);可以替换为return char;

答案 1 :(得分:0)

正如未说出口的问题似乎是

  

推荐的实施方法是什么?给定的解决方案看起来像胡言乱语。

更有效和可读的方式是:

function rotchar(char) {
  const code = char.charCodeAt(0)
  const isUpper = /[A-Z]/.test(char)
  const min = (isUpper ? 'A' : 'a').charCodeAt(0)

  return String.fromCharCode((((code - min) + 13) % 26) + min)
}

function rot13(str) {
  return str.replace(/[A-Z]/gi, rotchar)
}

console.log(rot13('Uryyb Jbeyq'))
console.log(rot13('Hello World'))

如果要实现通用rot(),可以创建工厂函数。请注意,rot13()是一种特殊情况,其中编码和解码是相同的操作。对于其余的,编码将数字偏移量添加到ASCII索引,同时解码减去数字偏移量:

function rot(offset, decode) {
  if (offset < 1 || offset > 25) {
    throw new RangeError('offset must be between 1 and 25')
  }

  // note that when decoding, rotation
  // performs (code + 26 - offset) % 26
  const rotate = decode ? 26 - offset : offset
  
  function rotchar(char) {
    const code = char.charCodeAt(0)
    const isUpper = /[A-Z]/.test(char)
    const min = (isUpper ? 'A' : 'a').charCodeAt(0)

    return String.fromCharCode((((code - min) + rotate) % 26) + min)
  }

  return function rotstr(str) {
    return str.replace(/[A-Z]/gi, rotchar)
  }
}

const rot13 = rot(13)

console.log('rot13:')
console.log(rot13('  Uryyb Jbeyq'))
console.log(rot13('  Hello World'))

const rot12encode = rot(12, false)
const rot12decode = rot(12, true)

console.log('rot12:')
console.log(rot12encode('  Hello World'))
console.log(rot12decode('  Tqxxa Iadxp'))