采用无点风格调用String.prototype.concat()未按预期运行的技术咨询
为什么直接传递
namespace.concat会报错? 这个问题其实是JavaScript里**函数上下文(this绑定)**的经典坑,咱来一步步理清楚:
先看正常运行的箭头函数版本
names.map((i) => namespace.concat(i))
这里箭头函数里调用namespace.concat(i)时,concat方法的this是明确绑定到namespace这个字符串上的——相当于你直接调用了字符串实例的concat方法,参数是数组元素,自然没问题。
再看报错的原因
当你写names.map(namespace.concat)时,你其实是把namespace上的concat方法单独抽出来传给了map。但map在调用这个函数的时候,只会把当前数组元素、索引、原数组作为参数传进去,不会帮你保留原来的this指向!
也就是说,此时concat方法执行时,它的this变成了undefined(严格模式下),而String.prototype.concat要求调用它的必须是一个字符串实例,所以就抛出了那个“called on null or undefined”的错误。
解决办法有这几个:
- 手动绑定
this:用bind把concat的this固定为namespacenames.map(namespace.concat.bind(namespace)) - 继续用箭头函数:就是你最初的写法,虽然多写了几行,但能明确保证
this的指向,可读性也不错 - 用模板字符串简化:字符串拼接场景下,模板字符串比
concat更直观names.map(name => `${namespace}${name}`)
补充一点你认知里的小误区
你说“a => fn(a)等价于直接调用fn”,这个结论只在fn是不依赖this的纯函数时成立!比如纯函数const double = x => x*2,arr.map(x => double(x))和arr.map(double)确实没区别,但如果fn是某个对象的方法、依赖this指向该对象,那直接传递方法就会丢失this绑定,就像你遇到的这个情况~
内容的提问来源于stack exchange,提问作者Boogie
相关产品推荐
相关产品推荐

