ServiceNow: reference vs. primitive data types
Tags: javascript, glideelement, gliderecord, servicenow
Published: 2023-03-23 21:25:33

Following code shows the correct and bad way how to work with field values using GlideRecord. It simply puts values into an array. Take time and go through the code, all explained after in detail:

```javascript
var prbArray_CORRECT = [];
var prbArray_WRONG = [];
var grPrb = new GlideRecord('problem');
grPrb.addQuery('active', true);
grPrb.query();
while(grPrb.next()) {
    // grPrb is iterable collection, it moves to the next element with each iteration
    // grPrb.number is object GlideElement, not string/integer/date
    // reference is pushed to array
    // Wrong way
    prbArray_WRONG.push(grPrb.number);
    // Correct way
    // grPrb.getValue('number') returns string
    // The same can be done by explicit retype:
    // grPrb.number + '';
    // grPrb.number.toString();
    // grPrb.number.getValue();
    prbArray_CORRECT.push(grPrb.getValue('number'));
}
gs.log(prbArray_CORRECT);
// Correct output: PRB0040003,PRB0040004,PRB0040005,PRB0040006,PRB0040007

gs.log(prbArray_WRONG);
// Unexpected output: PRB0040007,PRB0040007,PRB0040007,PRB0040007,PRB0040007
// Array prbArray_WRONG contains elements with the same value


```

The issue is `prbArray_WRONG` which stores unexpected values (all values are the same: PRB0040007,PRB0040007,PRB0040007,...) even though there were simply saved values of field `grPrb.number` for active problems. To tell what is happening, it is important to explain two principles. 

**The first** is related to JavaScript and **the second** is related to ServiceNow. 

### Object vs. primitive data type
**First principle:** when assigning value to a variable, **the type of value matters** in JavaScript. Primitive types (string, integers, boolean, null) are **assigned directly as value**, no confusion here. But object types are **assigned as reference** and are treated more as the pointer somewhere into memory where the object is stored. This is an important difference because it has consequences when working with objects. 

### ServiceNow GlideElement
**The second principle** is related to ServiceNow and is also a tricky one. Which type of value would you expect in `grPrb.number`? Let's try this: 

```javascript
// Is grPrb.number a string?
var grPrb = new GlideRecord('problem');
grPrb.addQuery('active', true);
grPrb.setLimit(1);
grPrb.query();
if (grPrb.next()) {
    gs.log(typeof grPrb.number);
    // Returns "object"
    gs.log(grPrb.number.constructor.name);
    // Returns "GlideElement"
}
```

![ServiceNow GlideElement](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/45od4jmiphiippva5cck.png)


Well, right, ehm it is object GlideElement. And this is the confusing part, because logically I would expect string (primitive type) in grPrb.number. 

When connecting these two principles, it explains what is happening: 
1) Putting `grPrb.number` into array means there is put reference to GlideElement object in each iteration instead of actual value of field
2) When the records' iteration is done, **all array elements reference to the last GlideElement**. Because "grPrb" is iterable > the current pointer is the last record at the end of iteration > all elements in the array now point to this last record. 

Confusing? Yes, it is not easy to get it and explain it. Important is to keep in mind that **whenever you do something with GlideRecord fields, just retype the value to the string or any other primitive data type** to avoid unexpected behavior. GlideElement provides a set of methods for dealing with fields and their values (see [documentation](https://docs.servicenow.com/en-US/bundle/utah-api-reference/page/app-store/dev_portal/API_reference/GlideElement_global/concept/c_GlideElementAPI.html)). When you convert into the primitive data type, it will be handled as value (not as object reference) in the array element/variable. It will save you headache and hours of debugging. As mentioned in the script, you can retype it in the following ways: 

`var prbNumber = grPrb.number + "";`
`var prbNumber = grPrb.number.toString();`
`var prbNumber = grPrb.number.getValue();`
`var prbNumber = grPrb.getValue('number');`
`var recordSysID = grPrb.getUniqueValue();`

If you need to pass a record _sys_id_ as an event parameter or a parameter in script include, you can use `getUniqueValue()`  [GlideRecord](https://docs.servicenow.com/bundle/utah-api-reference/page/app-store/dev_portal/API_reference/GlideRecord/concept/c_GlideRecordAPI.html) method. 

---
No matter if you work with field number, description, priority, sys_id the behavior is the same: GlideElement represents the field and if you need a field value, you need to use `getValue()`, `toString()` methods or explicitly retype it.

If you want to go deeper (and I recommend it) and understand the differences of how the primitive and reference data types work in JavaScript, check these posts. This principle is general and is fundamental for object-oriented programming languages. It is more technical but interesting to understand how computer works with memory:
https://www.freecodecamp.org/news/primitive-vs-reference-data-types-in-javascript/

https://ui.dev/primitive-vs-reference-values-in-javascript