携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第4天,点击查看活动详情。
filter 属性
实际问题
错误输出
let { filter = '' } = query;
let filterIds = [];
if (filter) {
try {
filter = decodeURI(filter);
filterIds = filter.split(',');
} catch (e) {
// ignore
}
}
console.log(filterIds); // 输出:['function filter() { [native code] }']`
期望实现
从 URL 的 query 对象中获取 filter 参数,并解析放入 filterIds 数组中,继而执行后续的筛选逻辑。
原因分析
query 对象被重新赋值过,新的 query 对象被初始化为 [],实际是 Array 的实例。
所以,当 query 对象实际并没有 filter 属性时,对 query 对象的 filter 属性的访问操作会搜寻该对象的原型,也就是 Array 对象,找到了名字匹配的 filter 方法。
解决方案
更换参数名,不用 filter 作为参数
原本的 query 对象的原型链上没有 filter 方法,新的 query 对象可以使用 Object.assign() 赋值
新的 query 对象应该初始化为 {},而不是 []
map 属性
在代码中,也会从 URL 的 query 对象中获取 map 参数,为什么这段逻辑没有出错?
原因:map 参数是数值判断,map==='1' 时执行,否则不执行相关逻辑;但是 filter 参数是空值判断,if (filter) {} 时执行,所以会一直执行相关逻辑。
所以,代码里的 map 参数取值其实也是有问题的,只是不同的判断方式导致这个问题没有什么影响。
对象原型
JavaScript 常被描述为一种基于原型的语言 (prototype-based language)——每个对象拥有一个原型对象,对象以其原型为模板、从原型继承方法和属性。
准确地说,这些属性和方法定义在 Object 的构造器函数 (constructor functions) 之上的prototype 属性上,而非对象实例本身。
解构判空
解构赋值语法是一种 Javascript 表达式。通过解构赋值,可以将属性/值从对象/数组中取出,赋值给其他变量。
- 解构对象时会查找原型链(如果属性不在对象自身,将从原型链中查找)
- 当被解构的对象是函数返回时,需要注意返回值不能为
null和undefined
function func() {};
const { a } = func(); // bad
// Uncaught TypeError: Cannot destructure property 'a' of 'func(...)' as it is undefined.
const { a } = func() || {}; // good