1# getTarget API: Obtaining Original Objects 2<!--Kit: ArkUI--> 3<!--Subsystem: ArkUI--> 4<!--Owner: @jiyujia926--> 5<!--Designer: @s10021109--> 6<!--Tester: @TerryTsao--> 7<!--Adviser: @zhang_yixin13--> 8 9To obtain the original object before a proxy is added by the state management framework, you can use the [getTarget](../../reference/apis-arkui/js-apis-StateManagement.md#gettarget) API. 10 11Before reading this topic, you are advised to review [\@Observed](./arkts-observed-and-objectlink.md) and [\@ObservedV2](./arkts-new-observedV2-and-trace.md). 12 13>**NOTE** 14> 15>The **getTarget** API in UIUtils is supported since API version 12. 16 17## Overview 18 19The state management framework adds proxies to original objects of the class, Date, Map, Set, and Array types to observe attribute changes and API invoking. Proxies will change the variable types. In scenarios such as type determination and Node-API invoking, unexpected results may be generated because the variable type is not the type of the original object. 20 21- Import the UIUtils to use the **getTarget** API. 22 23 ```ts 24 import { UIUtils } from '@kit.ArkUI'; 25 ``` 26 27- In state management V1, proxies are added to the following to observe changes in top-level properties or changes triggered by API calls: (1) instances of classes decorated with \@Observed; (2) objects of the Class, Date, Map, Set, and Array types decorated with [\@State](./arkts-state.md) or other state variable decorators. 28- In state management V2, proxies are added to the following to observe changes triggered by API calls: objects of the Date, Map, Set, and Array types decorated with [\@Trace](./arkts-new-observedV2-and-trace.md), [\@Local](./arkts-new-local.md), or other state variable decorators. 29 30The **getTarget** API is used to obtain the original objects of these proxy objects. 31 32## Constraints 33 34- Only the parameters of the object type can be passed by **getTarget**. 35 36 ```ts 37 import { UIUtils } from '@kit.ArkUI'; 38 let res = UIUtils.getTarget(2); // Incorrect usage. The input parameter is of the non-object type. 39 @Observed 40 class Info { 41 name: string = "Tom"; 42 } 43 let info: Info = new Info(); 44 let rawInfo: Info = UIUtils.getTarget (info); // Correct usage. 45 ``` 46 47- Changes to the content in the original object obtained by **getTarget** cannot be observed nor trigger UI re-renders. 48 49 ```ts 50 import { UIUtils } from '@kit.ArkUI'; 51 @Observed 52 class Info { 53 name: string = "Tom"; 54 } 55 @Entry 56 @Component 57 struct Index { 58 @State info: Info = new Info(); 59 60 build() { 61 Column() { 62 Text(`info.name: ${this.info.name}`) 63 Button(`Change Proxy Object Properties`) 64 .onClick(() => { 65 this.info.name = "Alice"; // The Text component can be re-rendered. 66 }) 67 Button(`Change Original Object Properties`) 68 .onClick(() => { 69 let rawInfo: Info = UIUtils.getTarget(this.info); 70 rawInfo.name = "Bob"; // The Text component cannot be re-rendered. 71 }) 72 } 73 } 74 } 75 ``` 76 77## Use Scenarios 78 79### Obtaining the Original Object Before Proxy Addition in State Management V1 80 81State management V1 adds proxies to the following objects: 82 831. Instances of classes decorated with \@Observed A proxy is automatically added to an instance of a class decorated with \@Observed when the instance is created. However, instances not initialized with the **new** operator are not proxied. 84 85```ts 86@Observed 87class ObservedClass { 88 name: string = "Tom"; 89} 90class NonObservedClass { 91 name: string = "Tom"; 92} 93let observedClass: ObservedClass = new ObservedClass(); // Proxied. 94let nonObservedClass: NonObservedClass = new NonObservedClass(); // Not proxied. 95``` 96 972. Complex-type objects decorated with state variable decorators Proxies are added to objects of the Class, Map, Set, Date, or Array type decorated with \@State, \@Prop, or other state variable decorators. If the object is already a proxy, no new proxy is added. 98 99```ts 100@Observed 101class ObservedClass { 102 name: string = "Tom"; 103} 104class NonObservedClass { 105 name: string = "Tom"; 106} 107let observedClass: ObservedClass = new ObservedClass(); // Proxied. 108let nonObservedClass: NonObservedClass = new NonObservedClass(); // Not proxied. 109@Entry 110@Component 111struct Index { 112 @State observedObject: ObservedClass = observedClass; // No new proxy is created (the object is already proxied). 113 @State nonObservedObject: NonObservedClass = nonObservedClass; // A proxy is created. 114 @State numberList: number[] = [1, 2, 3]; // A proxy is created for the Array type. 115 @State sampleMap: Map<number, string> = new Map([[0, "a"], [1, "b"], [3, "c"]]); // A proxy is created for the Map type. 116 @State sampleSet: Set<number> = new Set([0, 1, 2, 3, 4]); // A proxy is created for the Set type. 117 @State sampleDate: Date = new Date(); // A proxy is created for the Date type. 118 119 build() { 120 Column() { 121 Text(`this.observedObject === observedClass: ${this.observedObject === observedClass}`) // true 122 Text(`this.nonObservedObject === nonObservedClass: ${this.nonObservedObject === nonObservedClass}`) // false 123 } 124 } 125} 126``` 127 128Use **UIUtils.getTarget** to obtain the original objects before proxies are added. 129 130```ts 131import { UIUtils } from '@kit.ArkUI'; 132@Observed 133class ObservedClass { 134 name: string = "Tom"; 135} 136class NonObservedClass { 137 name: string = "Tom"; 138} 139let observedClass: ObservedClass = new ObservedClass(); // Proxied. 140let nonObservedClass: NonObservedClass = new NonObservedClass(); // Not proxied. 141let globalNumberList: number[] = [1, 2, 3]; // Not proxied. 142let globalSampleMap: Map<number, string> = new Map([[0, "a"], [1, "b"], [3, "c"]]); // Not proxied. 143let globalSampleSet: Set<number> = new Set([0, 1, 2, 3, 4]); // Not proxied. 144let globalSampleDate:Date = new Date (); // Not proxied. 145@Entry 146@Component 147struct Index { 148 @State observedObject: ObservedClass = observedClass; // No new proxy is created (the object is already proxied). 149 @State nonObservedObject: NonObservedClass = nonObservedClass; // A proxy is created. 150 @State numberList: number[] = globalNumberList; // A proxy is created for the Array type. 151 @State sampleMap: Map<number, string> = globalSampleMap; // A proxy is created for the Map type. 152 @State sampleSet: Set<number> = globalSampleSet; // A proxy is created for the Set type. 153 @State sampleDate: Date = globalSampleDate; // A proxy is created for the Date type. 154 155 build() { 156 Column() { 157 Text(`this.observedObject === observedClass: ${this.observedObject === 158 observedClass}`) // true 159 Text(`UIUtils.getTarget(this.nonObservedObject) === nonObservedClass: ${UIUtils.getTarget(this.nonObservedObject) === 160 nonObservedClass}`) // true 161 Text(`UIUtils.getTarget(this.numberList) === globalNumberList: ${UIUtils.getTarget(this.numberList) === 162 globalNumberList}`) // true 163 Text(`UIUtils.getTarget(this.sampleMap) === globalSampleMap: ${UIUtils.getTarget(this.sampleMap) === 164 globalSampleMap}`) // true 165 Text(`UIUtils.getTarget(this.sampleSet) === globalSampleSet: ${UIUtils.getTarget(this.sampleSet) === 166 globalSampleSet}`) // true 167 Text(`UIUtils.getTarget(this.sampleDate) === globalSampleDate: ${UIUtils.getTarget(this.sampleDate) === 168 globalSampleDate}`) // true 169 } 170 } 171} 172``` 173 174### Obtaining the Original Object Before Proxy Addition in State Management V2 175 176In state management V2, proxies are added to objects of the Map, Set, Date, and Array type decorated with \@Trace, \@Local, or other state variable decorators. Unlike in state management V1, no proxies are added to class instances in state management V2. 177 178```ts 179@ObservedV2 180class ObservedClass { 181 @Trace name: string = "Tom"; 182} 183let globalObservedObject: ObservedClass = new ObservedClass(); // Not proxied. 184let globalNumberList: number[] = [1, 2, 3]; // Not proxied. 185let globalSampleMap: Map<number, string> = new Map([[0, "a"], [1, "b"], [3, "c"]]); // Not proxied. 186let globalSampleSet: Set<number> = new Set([0, 1, 2, 3, 4]); // Not proxied. 187let globalSampleDate:Date = new Date (); // Not proxied. 188@Entry 189@ComponentV2 190struct Index { 191 @Local observedObject: ObservedClass = globalObservedObject; // Objects in V2 are not proxied. 192 @Local numberList: number[] = globalNumberList; // A proxy is created for the Array type. 193 @Local sampleMap: Map<number, string> = globalSampleMap; // A proxy is created for the Map type. 194 @Local sampleSet: Set<number> = globalSampleSet; // A proxy is created for the Set type. 195 @Local sampleDate: Date = globalSampleDate; // A proxy is created for the Date type. 196 197 build() { 198 Column() { 199 Text(`this.observedObject === globalObservedObject ${this.observedObject === globalObservedObject}`) // true 200 Text(`this.numberList === globalNumberList ${this.numberList === globalNumberList}`) // false 201 } 202 } 203} 204``` 205 206Use **UIUtils.getTarget** to obtain the original objects before proxies are added. 207 208```ts 209import { UIUtils } from '@kit.ArkUI'; 210@ObservedV2 211class ObservedClass { 212 @Trace name: string = "Tom"; 213} 214let globalObservedObject: ObservedClass = new ObservedClass(); // Not proxied. 215let globalNumberList: number[] = [1, 2, 3]; // Not proxied. 216let globalSampleMap: Map<number, string> = new Map([[0, "a"], [1, "b"], [3, "c"]]); // Not proxied. 217let globalSampleSet: Set<number> = new Set([0, 1, 2, 3, 4]); // Not proxied. 218let globalSampleDate:Date = new Date (); // Not proxied. 219@Entry 220@ComponentV2 221struct Index { 222 @Local observedObject: ObservedClass = globalObservedObject; // Objects in V2 are not proxied. 223 @Local numberList: number[] = globalNumberList; // A proxy is created for the Array type. 224 @Local sampleMap: Map<number, string> = globalSampleMap; // A proxy is created for the Map type. 225 @Local sampleSet: Set<number> = globalSampleSet; // A proxy is created for the Set type. 226 @Local sampleDate: Date = globalSampleDate; // A proxy is created for the Date type. 227 228 build() { 229 Column() { 230 Text(`this.observedObject === globalObservedObject ${this.observedObject === 231 globalObservedObject}`) // true 232 Text(`UIUtils.getTarget(this.numberList) === globalNumberList: ${UIUtils.getTarget(this.numberList) === 233 globalNumberList}`) // true 234 Text(`UIUtils.getTarget(this.sampleMap) === globalSampleMap: ${UIUtils.getTarget(this.sampleMap) === 235 globalSampleMap}`) // true 236 Text(`UIUtils.getTarget(this.sampleSet) === globalSampleSet: ${UIUtils.getTarget(this.sampleSet) === 237 globalSampleSet}`) // true 238 Text(`UIUtils.getTarget(this.sampleDate) === globalSampleDate: ${UIUtils.getTarget(this.sampleDate) === 239 globalSampleDate}`) // true 240 } 241 } 242} 243``` 244 245In state management V2, decorators generate getter and setter methods for the decorated variables, and add the **\_\_ob\_** prefix to the original variable names. For performance purposes, the **getTarget** API does not process the prefix added by decorators in V2. Therefore, when an instance of a class decorated with \@ObservedV2 is passed to the **getTarget** API, the returned object remains the instance itself, and the property name decorated with \@Trace still has the **\_\_ob\_** prefix. 246 247This prefix causes some Node-APIs to fail to process object properties as expected.<br>Example:<br>Affected Node-APIs include the following: 248 249```ts 250// Class decorated with @ObservedV2. 251@ObservedV2 252class Info { 253 @Trace name: string = "Tom"; 254 @Trace age: number = 24; 255} 256let info: Info = new Info(); // info instance passed in through Node-APIs. 257``` 258 259| Name | Result | 260| ----------------------- | ---------------------------------------------- | 261| napi_get_property_names | Returns property names with the **\_\_ob\_** prefix, for example, **\_\_ob\_name** or **\_\_ob\_age**. | 262| napi_set_property | Changes values successfully using the original name (for example, **name**) or the name with the **\_\_ob\_** prefix (for example, **\_\_ob\_name**). | 263| napi_get_property | Obtains values using the original name (for example, **name**) or the name with the **\_\_ob\_** prefix (for example, **\_\_ob\_name**). | 264| napi_has_property | Returns **true** for both the original name (for example, **name**) or the name with the **\_\_ob\_** prefix (for example, **\_\_ob\_name**). | 265| napi_delete_property | Requires the **\_\_ob\_** prefix for successful deletion.| 266| napi_has_own_property | Returns **true** for both the original name (for example, **name**) or the name with the **\_\_ob\_** prefix (for example, **\_\_ob\_name**). | 267| napi_set_named_property | Changes values successfully using the original name (for example, **name**) or the name with the **\_\_ob\_** prefix (for example, **\_\_ob\_name**). | 268| napi_get_named_property | Obtains values using the original name (for example, **name**) or the name with the **\_\_ob\_** prefix (for example, **\_\_ob\_name**). | 269| napi_has_named_property | Returns **true** for both the original name (for example, **name**) or the name with the **\_\_ob\_** prefix (for example, **\_\_ob\_name**). | 270