Objects¶
Objects are dynamic collections of key-value pairs. They store structured data and can be created, modified, and accessed at runtime.
Object Creation¶
Object Literal Syntax¶
Example:
Empty Object¶
Keys Must Be Strings¶
// CORRECT: String keys
object = {
name: "Alice",
age: 30,
123: "numeric string key",
};
// ERROR: Keys without quotes
// object = {
// name: "Alice", // ERROR
// age: 30 // ERROR
// };
Values Can Be Any Type¶
mixed = {
string: "text",
number: 42,
boolean: true,
null: null,
date: $Now(),
array: [1, 2, 3],
object: {
nested: "value",
},
};
Property Access¶
Dot Notation¶
Accessing Nested Properties¶
person = {
name: "Alice",
address: {
street: "123 Main St",
city: "Springfield",
zip: "12345",
},
};
city = person.address.city; // "Springfield"
zip = person.address.zip; // "12345"
Accessing Non-Existent Properties¶
Returns null:
object = { name: "Alice" };
value = object.age; // null (doesn't exist)
nested = object.address.city; // ERROR: Cannot access property of null
Safe access:
Dynamic Property Access¶
Using $GetValue¶
Get property value by name:
object = {
firstName: "John",
lastName: "Doe",
};
propertyName = "firstName";
value = $GetValue(object, propertyName); // "John"
Nested Property Access¶
person = {
name: "Alice",
contact: {
email: "alice@example.com",
},
};
// Nested access with dot notation
email = $GetValue(person, "contact.email"); // "alice@example.com"
Using $SetValue¶
Set property value by name:
Creating New Properties Dynamically¶
policy = {};
$SetValue(policy, "number", "POL-001");
$SetValue(policy, "premium", 1200);
$SetValue(policy, "coverage", 250000);
// policy is now:
// {
// "number": "POL-001",
// "premium": 1200,
// "coverage": 250000
// }
Modifying Objects¶
Adding Properties¶
Using .AddProperty()¶
customer = {
firstName: "John",
lastName: "Doe",
};
customer.AddProperty("email", "john@example.com");
email = customer.email; // "john@example.com"
Direct Assignment¶
object = {};
object.name = "Alice"; // ERROR: Cannot assign via dot notation
// Use .AddProperty() or $SetValue() instead
Note: EverSharp does not support property assignment via dot notation. Use .AddProperty() or $SetValue().
Updating Properties¶
customer = {
name: "Alice",
age: 30,
};
// Update using $SetValue
$SetValue(customer, "age", 31);
age = customer.age; // 31
Removing Properties¶
EverSharp does not have a built-in way to remove properties. Workaround:
// Create new object without unwanted property
original = {
name: "Alice",
age: 30,
temp: "remove this",
};
// Manual copy without 'temp'
filtered = {
name: original.name,
age: original.age,
};
Working with Objects¶
Copying Objects¶
Objects are reference types. Assignment creates a reference, not a copy:
original = {
name: "Alice",
age: 30,
};
reference = original;
$SetValue(reference, "age", 31);
age1 = original.age; // 31 (modified)
age2 = reference.age; // 31 (same object)
Shallow copy:
function shallowCopy(obj) {
copy = {};
// Manually copy each property
copy.AddProperty("name", obj.name);
copy.AddProperty("age", obj.age);
return copy;
}
Checking for Properties¶
object = {
name: "Alice",
age: 30,
};
// Check if property exists
name = $GetValue(object, "name");
hasName = name != null; // true
email = $GetValue(object, "email");
hasEmail = email != null; // false
Iterating Over Properties¶
EverSharp doesn't have built-in property iteration. Properties must be accessed by known names.
Nested Objects¶
Creating Nested Structures¶
policy = {
number: "POL-001",
premium: 1200,
customer: {
firstName: "John",
lastName: "Doe",
age: 35,
address: {
street: "123 Main St",
city: "Springfield",
state: "IL",
zip: "62701",
},
},
coverage: {
amount: 250000,
type: "Term Life",
years: 20,
},
};
Accessing Nested Data¶
customerName = policy.customer.firstName + " " + policy.customer.lastName;
city = policy.customer.address.city;
coverageType = policy.coverage.type;
Safe Nested Access¶
// Unsafe: Will error if intermediate property is null
// city = policy.customer.address.city;
// Safe: Check each level
if (
policy != null &&
policy.customer != null &&
policy.customer.address != null
) {
city = policy.customer.address.city;
}
Modifying Nested Properties¶
policy = {
number: "POL-001",
customer: {
name: "Alice",
},
};
// Update nested property
$SetValue(policy.customer, "age", 30);
age = policy.customer.age; // 30
Objects in Arrays¶
Array of Objects¶
customers = [
{ name: "Alice", age: 30 },
{ name: "Bob", age: 25 },
{ name: "Charlie", age: 35 },
];
// Access by index
firstCustomer = customers[0];
name = firstCustomer.name; // "Alice"
// Or combined
name = customers[0].name; // "Alice"
Filtering Objects¶
customers = [
{ name: "Alice", age: 30, isActive: true },
{ name: "Bob", age: 25, isActive: false },
{ name: "Charlie", age: 35, isActive: true },
];
// Get active customers
active = customers.Filter((c) => c.isActive);
// Get customers over 30
over30 = customers.Filter((c) => c.age > 30);
Mapping Objects¶
// Extract property
names = customers.Map((c) => c.name);
// ["Alice", "Bob", "Charlie"]
// Transform objects
simplified = customers.Map((c) => {
return {
name: c.name,
status: c.isActive ? "Active" : "Inactive",
};
});
Sorting Objects¶
// Sort by age
sortedByAge = customers.OrderBy((c) => c.age);
// Sort by name (descending)
sortedByName = customers.OrderByDescending((c) => c.name);
Common Patterns¶
Pattern 1: Object Builder¶
function createCustomer(firstName, lastName, age, email) {
customer = {};
customer.AddProperty("firstName", firstName);
customer.AddProperty("lastName", lastName);
customer.AddProperty("age", age);
customer.AddProperty("email", email);
customer.AddProperty("createdDate", $Today());
customer.AddProperty("isActive", true);
return customer;
}
customer = createCustomer("John", "Doe", 35, "john@example.com");
Pattern 2: Object Validation¶
function validateCustomer(customer) {
errors = [];
if (customer == null) {
errors.Push("Customer is null");
return errors;
}
if (customer.firstName == null || customer.firstName == "") {
errors.Push("First name required");
}
if (customer.age == null || customer.age < 18) {
errors.Push("Must be 18 or older");
}
if (customer.email == null || !customer.email.Contains("@")) {
errors.Push("Valid email required");
}
return errors;
}
Pattern 3: Object Transformation¶
function transformPolicyForExport(policy) {
return {
policyNumber: policy.number,
customerName: policy.customer.firstName + " " + policy.customer.lastName,
monthlyPremium: $Round(policy.premium / 12, 2),
coverageAmount: "$" + $ToString(policy.coverage),
status: policy.isActive ? "Active" : "Inactive",
};
}
policies = getPolicies();
exports = policies.Map((p) => transformPolicyForExport(p));
Pattern 4: Merging Objects¶
function merge(obj1, obj2) {
result = {};
// Copy from obj1 (manually, property by property)
result.AddProperty("name", obj1.name);
result.AddProperty("age", obj1.age);
// Copy from obj2
result.AddProperty("email", obj2.email);
result.AddProperty("phone", obj2.phone);
return result;
}
// Or use object literal
function merge(obj1, obj2) {
return {
name: obj1.name,
age: obj1.age,
email: obj2.email,
phone: obj2.phone,
};
}
Pattern 5: Default Values¶
function getCustomerEmail(customer) {
if (customer == null) {
return null;
}
email = customer.email;
if (email == null || email == "") {
return "no-email@example.com";
}
return email;
}
// Or using ternary
function getCustomerEmail(customer) {
return customer != null && customer.email != null && customer.email != ""
? customer.email
: "no-email@example.com";
}
Pattern 6: Nested Object Creation¶
function createPolicy(number, premium, customerData, coverageData) {
return {
number: number,
premium: premium,
isActive: true,
createdDate: $Today(),
customer: {
firstName: customerData.firstName,
lastName: customerData.lastName,
age: customerData.age,
contact: {
email: customerData.email,
phone: customerData.phone,
},
},
coverage: {
amount: coverageData.amount,
type: coverageData.type,
term: coverageData.term,
},
};
}
Objects as Function Returns¶
Returning Single Object¶
function createResult(success, message) {
return {
success: success,
message: message,
timestamp: $Now(),
};
}
result = createResult(true, "Operation completed");
if (result.success) {
$Log(result.message);
}
Returning Multiple Values¶
function calculatePremium(coverage, age) {
basePremium = coverage * 0.001;
if (age < 25) {
basePremium *= 1.5;
} else if (age > 65) {
basePremium *= 1.25;
}
monthlyPremium = basePremium / 12;
return {
annual: $Round(basePremium, 2),
monthly: $Round(monthlyPremium, 2),
ageCategory: age < 25 ? "young" : age > 65 ? "senior" : "standard",
};
}
premium = calculatePremium(250000, 30);
annual = premium.annual;
monthly = premium.monthly;
Error Handling Pattern¶
function processPayment(amount) {
if (amount <= 0) {
return {
success: false,
error: "Invalid amount",
errorCode: "INVALID_AMOUNT",
};
}
// Process payment
transactionId = generateTransactionId();
return {
success: true,
transactionId: transactionId,
processedAmount: amount,
timestamp: $Now(),
};
}
result = processPayment(100);
if (result.success) {
$Log("Payment successful: " + result.transactionId);
} else {
$Log("Error: " + result.error);
}
Best Practices¶
1. Use Descriptive Property Names¶
2. Group Related Data¶
// Less organized
customer = {
name: "John",
street: "123 Main",
city: "Springfield",
email: "john@example.com",
};
// Better organized
customer = {
name: "John",
address: {
street: "123 Main",
city: "Springfield",
},
contact: {
email: "john@example.com",
},
};
3. Check for Null Before Access¶
// Unsafe
city = policy.customer.address.city;
// Safe
if (
policy != null &&
policy.customer != null &&
policy.customer.address != null
) {
city = policy.customer.address.city;
}
4. Use Consistent Structure¶
// Consistent object structure
function createResponse(success, data, error) {
return {
success: success,
data: data,
error: error,
timestamp: $Now(),
};
}
// Always same structure
successResult = createResponse(true, { id: 123 }, null);
errorResult = createResponse(false, null, "Not found");
5. Validate Object Structure¶
function isValidCustomer(obj) {
if (obj == null) return false;
if (obj.firstName == null) return false;
if (obj.lastName == null) return false;
if (obj.age == null) return false;
return true;
}
if (isValidCustomer(customer)) {
// Safe to use
}
Common Mistakes¶
Mistake 1: Assuming Property Assignment Works¶
object = { name: "Alice" };
// ERROR: Cannot assign property this way
// object.age = 30;
// CORRECT: Use .AddProperty() or $SetValue()
object.AddProperty("age", 30);
// Or
$SetValue(object, "age", 30);
Mistake 2: Not Checking for Null¶
// ERROR: If customer is null, this fails
name = customer.firstName;
// CORRECT
if (customer != null) {
name = customer.firstName;
}
Mistake 3: Using Unquoted Keys¶
// ERROR: Keys must be strings
// object = { name: "Alice" };
// CORRECT
object = { name: "Alice" };
Mistake 4: Expecting Shallow Copy on Assignment¶
original = { name: "Alice" };
copy = original; // Reference, not copy!
$SetValue(copy, "name", "Bob");
name = original.name; // "Bob" (same object)
Mistake 5: Accessing Missing Nested Properties¶
customer = { name: "Alice" };
// ERROR: address is null
// city = customer.address.city;
// CORRECT
if (customer.address != null) {
city = customer.address.city;
}
Advanced Examples¶
Example 1: Complex Data Structure¶
policy = {
number: "POL-001",
status: "active",
dates: {
issued: $ToDate("2024-01-01"),
effective: $ToDate("2024-01-15"),
expires: $ToDate("2025-01-15"),
},
customer: {
id: "CUST-123",
personal: {
firstName: "John",
lastName: "Doe",
birthDate: $ToDate("1988-05-15"),
ssn: "***-**-1234",
},
contact: {
email: "john.doe@example.com",
phone: "(555) 123-4567",
address: {
street: "123 Main Street",
city: "Springfield",
state: "IL",
zip: "62701",
},
},
},
coverage: {
type: "Term Life",
amount: 250000,
term: 20,
beneficiaries: [
{ name: "Jane Doe", relationship: "Spouse", percentage: 100 },
],
},
premium: {
annual: 1200,
frequency: "monthly",
nextDue: $ToDate("2024-02-15"),
},
};
Example 2: Data Aggregation¶
function aggregateSales(orders) {
result = {
totalOrders: orders.Length,
totalRevenue: 0,
averageOrderValue: 0,
largestOrder: 0,
byCategory: {},
};
// Calculate totals
result.totalRevenue = orders.ReduceToNum((acc, o) => acc + o.total, 0);
result.averageOrderValue = $Round(
result.totalRevenue / result.totalOrders,
2
);
result.largestOrder = orders.ReduceToNum(
(acc, o) => (o.total > acc ? o.total : acc),
0
);
return result;
}
Example 3: Configuration Object¶
config = {
pricing: {
baseRate: 0.001,
ageFactors: {
under25: 1.5,
standard: 1.0,
over65: 1.25,
},
riskFactors: {
low: 0.9,
standard: 1.0,
high: 1.3,
},
},
limits: {
minCoverage: 50000,
maxCoverage: 1000000,
minAge: 18,
maxAge: 75,
},
discounts: {
loyaltyYears: [
{ years: 5, discount: 0.05 },
{ years: 10, discount: 0.1 },
{ years: 15, discount: 0.15 },
],
},
};
function calculatePremium(coverage, age, risk, years) {
baseRate = config.pricing.baseRate;
ageFactor =
age < 25
? config.pricing.ageFactors.under25
: age > 65
? config.pricing.ageFactors.over65
: config.pricing.ageFactors.standard;
riskFactor = $GetValue(config.pricing.riskFactors, risk);
premium = coverage * baseRate * ageFactor * riskFactor;
return $Round(premium, 2);
}
Next Steps¶
- Learn about arrays: Arrays
- Explore array methods with objects: Native Functions - Arrays
- See practical examples: Object Manipulation
- Understand dynamic access: Native Functions - Utilities