CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-vue--shared

Internal utility functions shared across Vue.js packages for DOM manipulation, type checking, and general utilities

Pending
Overview
Eval results
Files

object-utilities.mddocs/

Object and Array Utilities

General-purpose utilities for object manipulation, array operations, and data structure handling. These functions provide safe and consistent ways to work with JavaScript objects and arrays.

Capabilities

Object Manipulation

Core utilities for working with objects and their properties.

/**
 * Alias for Object.assign - merge objects
 * @param target - Target object to merge into
 * @param sources - Source objects to merge from
 * @returns Merged target object
 */
const extend: typeof Object.assign;

/**
 * Define a property on an object with specific descriptor options
 * @param obj - Object to define property on
 * @param key - Property key (string or symbol)
 * @param value - Property value
 * @param writable - Whether property is writable (default: false)
 */
function def(
  obj: object,
  key: string | symbol,
  value: any,
  writable?: boolean
): void;

Array Operations

Utilities for safely manipulating arrays.

/**
 * Remove element from array by value (mutates array)
 * Uses indexOf to find element, then splices it out
 * @param arr - Array to remove element from
 * @param el - Element to remove
 */
function remove<T>(arr: T[], el: T): void;

/**
 * Invoke array of functions with provided arguments
 * Safely calls each function in the array with the same arguments
 * @param fns - Array of functions to invoke
 * @param arg - Arguments to pass to each function
 */
function invokeArrayFns(fns: Function[], ...arg: any[]): void;

Value Comparison

Utilities for comparing values and detecting changes.

/**
 * Compare if value has changed, accounting for NaN equality
 * Uses Object.is for comparison (handles NaN and -0/+0 correctly)
 * @param value - New value
 * @param oldValue - Old value to compare against
 * @returns True if values are different
 */
function hasChanged(value: any, oldValue: any): boolean;

Number Conversion Utilities

Utilities for converting values to numbers with different behaviors.

/**
 * Loose number conversion - used for .number modifier in v-model
 * "123-foo" will be parsed to 123, "abc" remains "abc"
 * @param val - Value to convert
 * @returns Parsed number or original value if not numeric
 */
function looseToNumber(val: any): any;

/**
 * Strict number conversion for number-like strings only
 * "123-foo" will be returned as-is, "123" becomes number 123
 * @param val - Value to convert  
 * @returns Number if val is numeric string, otherwise original value
 */
function toNumber(val: any): any;

Constants and No-op Functions

Commonly used constant values and utility functions.

/**
 * Empty object - frozen in development, regular in production
 */
const EMPTY_OBJ: { readonly [key: string]: any };

/**
 * Empty array - frozen in development, regular in production
 */
const EMPTY_ARR: readonly never[];

/**
 * No-operation function that returns undefined
 */
const NOOP: () => void;

/**
 * Function that always returns false
 */
const NO: () => false;

Usage Examples:

import { 
  extend, def, remove, invokeArrayFns, hasChanged,
  EMPTY_OBJ, EMPTY_ARR, NOOP, NO
} from "@vue/shared";

// Object merging with extend
const target = { a: 1, b: 2 };
const source1 = { b: 3, c: 4 };
const source2 = { c: 5, d: 6 };

const merged = extend(target, source1, source2);
console.log(merged); // { a: 1, b: 3, c: 5, d: 6 }
console.log(merged === target); // true (mutates target)

// Property definition
const obj = {};
def(obj, "hiddenProp", "secret", false); // not writable
def(obj, "writableProp", "public", true); // writable

console.log(obj.hiddenProp); // "secret"
console.log(Object.getOwnPropertyDescriptor(obj, "hiddenProp"));
// { value: "secret", writable: false, enumerable: false, configurable: true }

// Array element removal
const items = ["a", "b", "c", "b", "d"];
remove(items, "b"); // Removes first occurrence
console.log(items); // ["a", "c", "b", "d"]

remove(items, "x"); // No effect if element not found
console.log(items); // ["a", "c", "b", "d"]

// Function array invocation
const callbacks = [
  (msg: string) => console.log(`Callback 1: ${msg}`),
  (msg: string) => console.log(`Callback 2: ${msg}`),
  (msg: string) => console.log(`Callback 3: ${msg}`)
];

invokeArrayFns(callbacks, "Hello World");
// Logs:
// "Callback 1: Hello World"
// "Callback 2: Hello World" 
// "Callback 3: Hello World"

// Empty callback arrays are handled safely
invokeArrayFns([], "message"); // No effect

// Change detection
console.log(hasChanged(1, 1)); // false
console.log(hasChanged(1, 2)); // true
console.log(hasChanged(NaN, NaN)); // false (Object.is handles NaN correctly)
console.log(hasChanged(0, -0)); // true (Object.is distinguishes -0/+0)
console.log(hasChanged(null, undefined)); // true

// Using constants
const defaultConfig = extend({}, EMPTY_OBJ, { theme: "dark" });
console.log(defaultConfig); // { theme: "dark" }

const emptyList = EMPTY_ARR.slice(); // Create new array from empty template
console.log(emptyList); // []

// No-op functions
const cleanup = NOOP; // Safe default cleanup function
const isDisabled = NO; // Function that always returns false

// Property definition with symbols
const secretKey = Symbol("secret");
def(obj, secretKey, "hidden value");
console.log(obj[secretKey]); // "hidden value"

// Number conversion utilities
console.log(looseToNumber("123")); // 123
console.log(looseToNumber("123.45")); // 123.45
console.log(looseToNumber("123-foo")); // 123 (parses what it can)
console.log(looseToNumber("abc")); // "abc" (returns as-is)

console.log(toNumber("123")); // 123
console.log(toNumber("123.45")); // 123.45
console.log(toNumber("123-foo")); // "123-foo" (returns as-is)
console.log(toNumber("abc")); // "abc" (returns as-is)

Object Safety Patterns

// Safe object merging patterns
function mergeConfig(userConfig: any) {
  // Always start with empty object to avoid mutations
  return extend({}, defaultConfig, userConfig);
}

// Safe property definition
function defineHiddenProperty(obj: object, key: string, value: any) {
  def(obj, key, value, false); // Non-writable by default
}

// Safe array cleanup
function cleanupCallbacks(callbacks: Function[]) {
  // Remove all callbacks
  callbacks.splice(0, callbacks.length);
}

Performance Characteristics

  • extend: Direct alias to Object.assign - native performance
  • remove: O(n) operation using indexOf + splice
  • def: Uses Object.defineProperty with optimized defaults
  • hasChanged: Uses Object.is which is optimized for equality checking
  • invokeArrayFns: Simple loop, no array methods overhead

Development vs Production Behavior

  • EMPTY_OBJ: Frozen in development to catch mutations, regular object in production
  • EMPTY_ARR: Frozen in development to catch mutations, regular array in production
  • This helps catch bugs during development while maintaining performance in production

Integration Patterns

These utilities are used throughout Vue's internals:

  • Component Props: extend for merging prop defaults
  • Event Systems: invokeArrayFns for calling multiple event handlers
  • Reactivity: hasChanged for detecting when reactive values change
  • Property Definition: def for defining non-enumerable properties on reactive objects

Install with Tessl CLI

npx tessl i tessl/npm-vue--shared

docs

display-utilities.md

dom-configuration.md

environment-utilities.md

equality-utilities.md

html-security.md

index.md

normalization.md

object-utilities.md

reactive-flags.md

string-transformations.md

type-checking.md

tile.json