为什么JavaScript中Symbol.isConcatSpreadable不可写?实测却能修改值?
为什么Symbol.isConcatSpreadable特性显示不可写,但实例上能修改值?
嘿,这个矛盾点其实是搞混了原型链上的属性特性和实例自身属性的区别,咱们把它拆明白:
首先,你查到的「可写性、可枚举性、可配置性都是否」,指的是Array.prototype上的Symbol.isConcatSpreadable属性。你可以用这段代码验证:
Object.getOwnPropertyDescriptor(Array.prototype, Symbol.isConcatSpreadable) // 返回:{ value: true, writable: false, enumerable: false, configurable: false }这个原型上的属性确实不能直接修改,如果你尝试
Array.prototype[Symbol.isConcatSpreadable] = false,严格模式下会直接报错,非严格模式下修改也不会生效。但你测试时写的
a[Symbol.isConcatSpreadable] = false,是在数组实例a的自身属性上新增了一个同名属性,并不是修改原型上的那个。JS的原型链规则里,实例可以自由添加自己的属性来覆盖原型链继承来的值——这个实例属性的默认特性是可写、可枚举、可配置的,自然能成功设置。你可以再验证一下实例自身的属性特性:
var a = [1,2,3]; a[Symbol.isConcatSpreadable] = false; Object.getOwnPropertyDescriptor(a, Symbol.isConcatSpreadable) // 返回:{ value: false, writable: true, enumerable: true, configurable: true }最后,
concat方法在判断是否要展开目标数组时,会优先读取实例自身的Symbol.isConcatSpreadable属性值,所以你设置false后,concat就不会展开a,于是得到了[4, 5, 6, Array(3)]的结果。
内容的提问来源于stack exchange,提问作者PageUpMe
相关产品推荐
相关产品推荐

