1# ArkCompiler子系统变更说明 2 3## cl.arkcompiler.1 在Array上查找属性以及设置属性的行为变更说明 4 5**访问级别** 6 7公开接口 8 9**变更原因** 10 11ECMAScript 规范中规定,当对某些Array实例进行某些查询,而查询的属性在Array实例自身上不存在时,需遍历原型链来执行查询。由于部分非StableArray的情况被识别为StableArray,导致跳过了原型链查询,查询结果与 ECMAScript 规范所定义的预期结果不一致。 12 13**变更影响** 14 15此变更不涉及应用适配。 16 17**变更前** 18 19- 情况一:当一个对象(o)是Array类型的实例时,通过特定方式(`fill, push, splice, unshift`)修改(Array.prototype),部分接口(`concat, slice, at, reduce, reverse`)无法正确从(o)上读取到(Array.prototype)上的元素,返回错误结果。 20- 情况二:当一个类MyArray继承自Array,对象(o)是MyArray的实例时,(o)上的constructor属性未被正确调用,导致对(o)调用`instance of`时返回结果错误。 21- 情况三:当一个类MyArray继承自Array,对象(o)是MyArray的实例时,修改MyArray.prototype.proto,部分接口(`concat, slice, at, reduce, reverse`)无法正确从(o)上读取到MyArray.prototype.proto上的元素,返回结果错误。 22- 情况四:当一个类MyArray继承自Array,对象(o)是MyArray的实例时,向(MyArray.prototype)中插入元素,部分接口(`concat, slice, at, reduce, reverse`)无法正确从(o)上读取到(MyArray.prototype)上的元素,返回结果错误。 23 24```js 25// 情况一: 26function BehaviorChange1() { 27// 以下有四种方法修改Array.prototype, 效果都是让Array.prototype = [233, 233, 233], 不同代码之间是并列关系 28// ----------------- 方法1 ----------------- 29 let arr1 = new Array(10); 30 arr1.__proto__.length = 3; 31 arr1.__proto__.fill(233, 0, 3); 32// ----------------- 方法1 ----------------- 33 34// ----------------- 方法2 ----------------- 35 let arr1 = new Array(10); 36 arr1.__proto__.push(233, 233, 233); 37// ----------------- 方法2 ----------------- 38 39// ----------------- 方法3 ----------------- 40 let arr1 = new Array(10); 41 arr1.__proto__.length = 3; 42 arr1.__proto__.splice(1, 0, 233, 233, 233); 43// ----------------- 方法3 ----------------- 44 45// ----------------- 方法4 ----------------- 46 let arr1 = new Array(10); 47 arr1.__proto__.unshift(233, 233, 233); 48// ----------------- 方法4 ----------------- 49 50 let arr2 = new Array(10); 51 let arr3 = arr1.concat(arr2); 52 print(arr3[11]); // 输出:undefined,不符合规范 53 54 let arr4 = arr1.slice(1); 55 print(arr4[0]); // 输出:undefined,不符合规范 56 57 let res = arr1.at(1); 58 print(res); // 输出:undefined,不符合规范 59 60 const sum = arr1.reduce((accumulator, currentValue) => { 61 return accumulator + currentValue; 62 }) 63 print(sum); // 输出:undefined,不符合规范 64 65 arr1.reverse(); 66 print(arr1[1]); //输出: undefined,不符合规范 67} 68BehaviorChange1(); 69 70// 情况二: 71function BehaviorChange2() { 72 class MyArray extends Array {} 73 let custom = new MyArray(1, 2, 3); 74 let result1 = custom.concat([4, 5]); 75 print(result1 instanceof MyArray); // 输出:false,不符合规范 76 77 let result2 = custom.slice(1); 78 print(result2 instanceof MyArray); // 输出:false,不符合规范 79} 80BehaviorChange2() 81 82// 情况三: 83function BehaviorChange3() { 84 class MyArray extends Array {} 85 let arr1 = new MyArray(10); 86 MyArray.prototype.__proto__ = [233, 233, 233]; 87 let arr2 = new Array(10); 88 let arr3 = arr1.concat(arr2); 89 print(arr3[1]); // 输出:undefined,不符合规范 90 91 let arr4 = arr1.slice(1); 92 print(arr4[0]); // 输出:undefined,不符合规范 93 94 let res = arr1.at(1); 95 print(res); // 输出:undefined,不符合规范 96 97 const sum = arr1.reduce((accumulator, currentValue) => { 98 return accumulator + currentValue; 99 }) 100 print(sum); // 输出:undefined,不符合规范 101 102 arr1.reverse(); 103 print(arr1[1]); //输出: undefined,不符合规范 104} 105BehaviorChange3(); 106 107// 情况四: 108function BehaviorChange4() { 109 class MyArray extends Array {} 110 let arr1 = new MyArray(10); 111 MyArray.prototype[0] = 233; 112 MyArray.prototype[1] = 233; 113 MyArray.prototype[2] = 233; 114 115 let arr2 = new Array(10); 116 let arr3 = arr1.concat(arr2); 117 print(arr3[1]); // 输出:undefined,不符合规范 118 119 let arr4 = arr1.slice(1); 120 print(arr4[0]); // 输出:undefined,不符合规范 121 122 let res = arr1.at(1); 123 print(res); // 输出:undefined,不符合规范 124 125 const sum = arr1.reduce((accumulator, currentValue) => { 126 return accumulator + currentValue; 127 }) 128 print(sum); // 输出:undefined,不符合规范 129 130 arr1.reverse(); 131 print(arr1[1]); //输出: undefined,不符合规范 132} 133BehaviorChange4(); 134``` 135**变更后** 136 137- 情况一:当一个对象(o)是Array类型的实例时,通过特定方式(`fill, push, splice, unshift`)修改(Array.prototype),接口(`concat, slice, at, reduce, reverse`)正确从(o)上读取到(Array.prototype)上的元素,返回正确结果(不兼容变更)。 138- 情况二:当一个类MyArray继承自Array,对象(o)是MyArray的实例时,(o)上的constructor属性未被正确调用,对(o)调用`instance of`时返回正确结果(不兼容变更)。 139- 情况三:当一个类MyArray继承自Array,对象(o)是MyArray的实例时,修改MyArray.prototype.proto,接口(`concat, slice, at, reduce, reverse`)正确从(o)上读取到MyArray.prototype.proto上的元素,返回正确结果(不兼容变更)。 140- 情况四:当一个类MyArray继承自Array,对象(o)是MyArray的实例时,向(MyArray.prototype)中插入元素,接口(`concat, slice, at, reduce, reverse`)正确从(o)上读取到(MyArray.prototype)上的元素,返回正确结果(不兼容变更)。 141 142```js 143// 情况一: 144function BehaviorChange1() { 145// 以下有四种方法修改Array.prototype, 效果都是让Array.prototype = [233, 233, 233], 不同代码之间是并列关系 146// ----------------- 方法1 ----------------- 147 let arr1 = new Array(10); 148 arr1.__proto__.length = 3; 149 arr1.__proto__.fill(233, 0, 3); 150// ----------------- 方法1 ----------------- 151 152// ----------------- 方法2 ----------------- 153 let arr1 = new Array(10); 154 arr1.__proto__.push(233, 233, 233); 155// ----------------- 方法2 ----------------- 156 157// ----------------- 方法3 ----------------- 158 let arr1 = new Array(10); 159 arr1.__proto__.length = 3; 160 arr1.__proto__.splice(1, 0, 233, 233, 233); 161// ----------------- 方法3 ----------------- 162 163// ----------------- 方法4 ----------------- 164 let arr1 = new Array(10); 165 arr1.__proto__.unshift(233, 233, 233); 166// ----------------- 方法4 ----------------- 167 168 let arr2 = new Array(10); 169 let arr3 = arr1.concat(arr2); 170 print(arr3[11]); // 输出:233 符合规范,concat的时候当自身没有时会遍历原型链 171 172 let arr4 = arr1.slice(1); 173 print(arr4[0]); // 输出:233 符合规范,slice的时候当自身没有时会遍历原型链 174 175 let res = arr1.at(1); 176 print(res); // 输出:233 符合规范,at的时候当自身没有时会遍历原型链 177 178 const sum = arr1.reduce((accumulator, currentValue) => { 179 return accumulator + currentValue; 180 }) 181 print(sum); // 输出:699 符合规范,reduce的时候当自身没有时会遍历原型链 182 183 arr1.reverse(); 184 print(arr1[1]); //输出: 233 符合规范,reverse的时候当自身没有时会遍历原型链 185} 186BehaviorChange1(); 187 188// 情况二: 189function BehaviorChange2() { 190 class MyArray extends Array {} 191 let custom = new MyArray(1, 2, 3); 192 let result1 = custom.concat([4, 5]); 193 print(result1 instanceof MyArray); // 输出:true 符合规范,custom上的constructor方法被正确调用 194 195 let result2 = custom.slice(1); 196 print(result2 instanceof MyArray); // 输出:true 符合规范,custom上的constructor方法被正确调用 197} 198BehaviorChange2() 199 200// 情况三: 201function BehaviorChange3() { 202 class MyArray extends Array {} 203 let arr1 = new MyArray(10); 204 MyArray.prototype.__proto__ = [233, 233, 233]; 205 let arr2 = new Array(10); 206 let arr3 = arr1.concat(arr2); 207 print(arr3[1]); // 输出:233 符合规范,concat的时候当自身没有时会遍历原型链 208 209 let arr4 = arr1.slice(1); 210 print(arr4[0]); // 输出:233 符合规范,slice的时候当自身没有时会遍历原型链 211 212 let res = arr1.at(1); 213 print(res); // 输出:233 符合规范,at的时候当自身没有时会遍历原型链 214 215 const sum = arr1.reduce((accumulator, currentValue) => { 216 return accumulator + currentValue; 217 }) 218 print(sum); // 输出:233 符合规范,reduce的时候当自身没有时会遍历原型链 219 220 arr1.reverse(); 221 print(arr1[1]); //输出: 233 符合规范,reverse的时候当自身没有时会遍历原型链 222} 223BehaviorChange3(); 224 225// 情况四: 226function BehaviorChange4() { 227 class MyArray extends Array {} 228 let arr1 = new MyArray(10); 229 MyArray.prototype[0] = 233; 230 MyArray.prototype[1] = 233; 231 MyArray.prototype[2] = 233; 232 233 let arr2 = new Array(10); 234 let arr3 = arr1.concat(arr2); 235 print(arr3[1]); // 输出:233 符合规范,concat的时候当自身没有时会遍历原型链 236 237 let arr4 = arr1.slice(1); 238 print(arr4[0]); // 输出:233 符合规范,slice的时候当自身没有时会遍历原型链 239 240 let res = arr1.at(1); 241 print(res); // 输出:233 符合规范,at的时候当自身没有时会遍历原型链 242 243 const sum = arr1.reduce((accumulator, currentValue) => { 244 return accumulator + currentValue; 245 }) 246 print(sum); // 输出:699 符合规范,reduce的时候当自身没有时会遍历原型链 247 248 arr1.reverse(); 249 print(arr1[1]); // 输出: 233 符合规范,reverse的时候当自身没有时会遍历原型链 250} 251BehaviorChange4(); 252 253 254``` 255 256**起始API Level** 257 258API 9 259 260**变更发生版本** 261 262从OpenHarmony 5.1.0.45 版本开始。 263 264**变更的接口/组件** 265 266涉及Array中`instance of, concat, slice, at, reduce, reverse`接口,详细触发操作见上文。 267 268**适配指导** 269 270在Array上查找属性时注意返回值的变更。 271