10.4-Object-Static-Methods
7.4 Object Static Methods
Table of Contents
- ā¢Introduction
- ā¢Object Creation Methods
- ā¢Property Enumeration Methods
- ā¢Object Manipulation Methods
- ā¢Object Inspection Methods
- ā¢Object Protection Methods
- ā¢Prototype Methods
- ā¢Modern Object Methods
- ā¢Method Comparison Tables
- ā¢Best Practices
Introduction
JavaScript's Object constructor provides many static methods that operate on objects. These are called on Object itself, not on object instances.
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā Object Static Methods Categories ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¤
ā ā
ā Creation āāāāāāāŗ Object.create() ā
ā Object.assign() ā
ā Object.fromEntries() ā
ā ā
ā Enumeration āāāāāāāŗ Object.keys() ā
ā Object.values() ā
ā Object.entries() ā
ā ā
ā Inspection āāāāāāāŗ Object.is() ā
ā Object.hasOwn() ā
ā Object.getOwnPropertyNames() ā
ā ā
ā Protection āāāāāāāŗ Object.freeze() ā
ā Object.seal() ā
ā Object.preventExtensions() ā
ā ā
ā Prototype āāāāāāāŗ Object.getPrototypeOf() ā
ā Object.setPrototypeOf() ā
ā ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
Object Creation Methods
Object.create()
Creates a new object with the specified prototype and optional property descriptors.
// Create object with specific prototype
const personProto = {
greet() {
return `Hello, I'm ${this.name}`;
},
};
const person = Object.create(personProto);
person.name = 'Alice';
console.log(person.greet()); // "Hello, I'm Alice"
// Create object with null prototype (no inherited properties)
const pureDict = Object.create(null);
pureDict.key = 'value';
console.log(pureDict.toString); // undefined (no Object.prototype)
// Create object with property descriptors
const config = Object.create(null, {
apiUrl: {
value: 'https://api.example.com',
writable: false,
enumerable: true,
},
timeout: {
value: 5000,
writable: true,
enumerable: true,
},
});
Object.assign()
Copies enumerable own properties from source objects to a target object.
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā Object.assign() Flow ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¤
ā ā
ā target source1 source2 ā
ā āāāāāāā āāāāāāā āāāāāāā ā
ā ā a:1 ā āāā ā b:2 ā āāā ā c:3 ā ā
ā āāāāāāā āāāāāāā ā b:9 ā ā
ā āāāāāāā ā
ā ā
ā Result: { a:1, b:9, c:3 } (later sources override) ā
ā ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
// Basic usage
const target = { a: 1 };
const source = { b: 2, c: 3 };
const result = Object.assign(target, source);
console.log(result); // { a: 1, b: 2, c: 3 }
console.log(target === result); // true (mutates target)
// Multiple sources (later overrides earlier)
const combined = Object.assign({}, { a: 1, b: 1 }, { b: 2, c: 2 }, { c: 3 });
console.log(combined); // { a: 1, b: 2, c: 3 }
// Shallow copy
const original = { nested: { x: 1 } };
const copy = Object.assign({}, original);
copy.nested.x = 99;
console.log(original.nested.x); // 99 (same nested object!)
Object.fromEntries()
Creates an object from an array of key-value pairs (inverse of Object.entries()).
// From entries array
const entries = [
['name', 'Alice'],
['age', 30],
];
const obj = Object.fromEntries(entries);
console.log(obj); // { name: "Alice", age: 30 }
// From Map
const map = new Map([
['x', 1],
['y', 2],
]);
const fromMap = Object.fromEntries(map);
console.log(fromMap); // { x: 1, y: 2 }
// Transform object properties
const prices = { apple: 1.5, banana: 0.75, cherry: 2.0 };
const doubled = Object.fromEntries(
Object.entries(prices).map(([key, value]) => [key, value * 2])
);
console.log(doubled); // { apple: 3, banana: 1.5, cherry: 4 }
Property Enumeration Methods
Object.keys()
Returns an array of object's own enumerable property names.
const user = {
name: 'Alice',
age: 30,
email: 'alice@example.com',
};
console.log(Object.keys(user));
// ["name", "age", "email"]
// Only own properties
const child = Object.create({ inherited: true });
child.own = 'property';
console.log(Object.keys(child)); // ["own"]
Object.values()
Returns an array of object's own enumerable property values.
const user = {
name: 'Alice',
age: 30,
email: 'alice@example.com',
};
console.log(Object.values(user));
// ["Alice", 30, "alice@example.com"]
// Practical use: sum values
const scores = { math: 95, english: 87, science: 92 };
const total = Object.values(scores).reduce((sum, v) => sum + v, 0);
console.log(total); // 274
Object.entries()
Returns an array of object's own enumerable [key, value] pairs.
const user = {
name: 'Alice',
age: 30,
};
console.log(Object.entries(user));
// [["name", "Alice"], ["age", 30]]
// Iterate with destructuring
for (const [key, value] of Object.entries(user)) {
console.log(`${key}: ${value}`);
}
// Convert to Map
const map = new Map(Object.entries(user));
console.log(map.get('name')); // "Alice"
Object.getOwnPropertyNames()
Returns ALL own property names, including non-enumerable ones.
const obj = { visible: true };
Object.defineProperty(obj, 'hidden', {
value: 'secret',
enumerable: false,
});
console.log(Object.keys(obj));
// ["visible"]
console.log(Object.getOwnPropertyNames(obj));
// ["visible", "hidden"]
Object.getOwnPropertySymbols()
Returns all own Symbol property keys.
const sym1 = Symbol('id');
const sym2 = Symbol('secret');
const obj = {
name: 'Object',
[sym1]: 12345,
[sym2]: 'hidden',
};
console.log(Object.keys(obj)); // ["name"]
console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(id), Symbol(secret)]
Object Manipulation Methods
Reflect.ownKeys()
Returns ALL own property keys (strings AND symbols).
const sym = Symbol('key');
const obj = {
normal: 'value',
[sym]: 'symbol value',
};
Object.defineProperty(obj, 'hidden', {
value: 'non-enumerable',
enumerable: false,
});
console.log(Reflect.ownKeys(obj));
// ["normal", "hidden", Symbol(key)]
Object.getOwnPropertyDescriptor()
Returns the property descriptor for a specific property.
const obj = { name: 'Alice' };
const descriptor = Object.getOwnPropertyDescriptor(obj, 'name');
console.log(descriptor);
/*
{
value: "Alice",
writable: true,
enumerable: true,
configurable: true
}
*/
Object.getOwnPropertyDescriptors()
Returns descriptors for ALL own properties.
const obj = {
name: 'Alice',
get fullName() {
return this.name;
},
};
console.log(Object.getOwnPropertyDescriptors(obj));
/*
{
name: {
value: "Alice",
writable: true,
enumerable: true,
configurable: true
},
fullName: {
get: [Function: get fullName],
set: undefined,
enumerable: true,
configurable: true
}
}
*/
Object Inspection Methods
Object.is()
Compares two values for sameness (similar to === but handles edge cases).
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā Object.is() vs === vs == ā
āāāāāāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāā¬āāāāāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāā¤
ā Comparison ā Object.is() ā === ā == ā
āāāāāāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāā¼āāāāāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāā¤
ā NaN === NaN ā true ā false ā false ā
ā +0 === -0 ā false ā true ā true ā
ā 5 === 5 ā true ā true ā true ā
ā "5" === 5 ā false ā false ā true ā
ā null === undef ā false ā false ā true ā
āāāāāāāāāāāāāāāāāāāā“āāāāāāāāāāāāāāā“āāāāāāāāāāāāāā“āāāāāāāāāāāāāāāāāāāā
// NaN handling
console.log(NaN === NaN); // false
console.log(Object.is(NaN, NaN)); // true
// Signed zero handling
console.log(+0 === -0); // true
console.log(Object.is(+0, -0)); // false
// Regular equality
console.log(Object.is(5, 5)); // true
console.log(Object.is({}, {})); // false (different objects)
Object.hasOwn() (ES2022)
Checks if object has specified own property (preferred over hasOwnProperty).
const user = {
name: 'Alice',
hasOwnProperty: 'overridden!', // Common gotcha
};
// Safe check with Object.hasOwn()
console.log(Object.hasOwn(user, 'name')); // true
console.log(Object.hasOwn(user, 'toString')); // false (inherited)
// Object.prototype.hasOwnProperty can break
// console.log(user.hasOwnProperty("name")); // Error!
Object.prototype.isPrototypeOf()
Checks if an object exists in another object's prototype chain.
const animal = { eats: true };
const dog = Object.create(animal);
console.log(animal.isPrototypeOf(dog)); // true
console.log(Object.prototype.isPrototypeOf(dog)); // true
Object Protection Methods
Object.freeze()
Makes object completely immutable (no changes allowed).
const frozen = Object.freeze({
name: 'Frozen',
data: { x: 1 },
});
frozen.name = 'Changed'; // Silently fails
frozen.newProp = 'new'; // Silently fails
delete frozen.name; // Silently fails
console.log(frozen); // { name: "Frozen", data: { x: 1 } }
// WARNING: Nested objects are NOT frozen
frozen.data.x = 999;
console.log(frozen.data.x); // 999
Object.seal()
Prevents adding/removing properties but allows modifying values.
const sealed = Object.seal({
name: 'Sealed',
count: 0,
});
sealed.count = 100; // Works!
sealed.newProp = 'new'; // Silently fails
delete sealed.name; // Silently fails
console.log(sealed); // { name: "Sealed", count: 100 }
Object.preventExtensions()
Prevents adding new properties only.
const limited = Object.preventExtensions({
existing: 'value',
});
limited.existing = 'modified'; // Works
limited.newProp = 'new'; // Silently fails
delete limited.existing; // Works!
console.log(Object.isExtensible(limited)); // false
Protection Check Methods
const obj = { x: 1 };
Object.freeze(obj);
console.log(Object.isFrozen(obj)); // true
console.log(Object.isSealed(obj)); // true (frozen implies sealed)
console.log(Object.isExtensible(obj)); // false
Prototype Methods
Object.getPrototypeOf()
Returns the prototype of an object.
const arr = [1, 2, 3];
console.log(Object.getPrototypeOf(arr) === Array.prototype); // true
const obj = {};
console.log(Object.getPrototypeOf(obj) === Object.prototype); // true
const nullProto = Object.create(null);
console.log(Object.getPrototypeOf(nullProto)); // null
Object.setPrototypeOf()
Sets the prototype of an object (use sparingly - performance impact).
const animal = {
speak() {
console.log('Some sound');
},
};
const dog = {
bark() {
console.log('Woof!');
},
};
Object.setPrototypeOf(dog, animal);
dog.speak(); // "Some sound"
dog.bark(); // "Woof!"
// ā ļø Warning: setPrototypeOf is slow, prefer Object.create()
Modern Object Methods
Object.groupBy() (ES2024)
Groups elements by a key returned from a callback.
const people = [
{ name: 'Alice', age: 25, department: 'Engineering' },
{ name: 'Bob', age: 30, department: 'Marketing' },
{ name: 'Charlie', age: 28, department: 'Engineering' },
];
const byDepartment = Object.groupBy(people, (person) => person.department);
console.log(byDepartment);
/*
{
Engineering: [
{ name: "Alice", age: 25, department: "Engineering" },
{ name: "Charlie", age: 28, department: "Engineering" }
],
Marketing: [
{ name: "Bob", age: 30, department: "Marketing" }
]
}
*/
Method Comparison Tables
Property Access Methods
| Method | Enumerable | Non-Enumerable | Symbols | Inherited |
|---|---|---|---|---|
Object.keys() | ā | ā | ā | ā |
Object.values() | ā | ā | ā | ā |
Object.entries() | ā | ā | ā | ā |
Object.getOwnPropertyNames() | ā | ā | ā | ā |
Object.getOwnPropertySymbols() | ā | ā | ā | ā |
Reflect.ownKeys() | ā | ā | ā | ā |
for...in | ā | ā | ā | ā |
Protection Levels
| Method | Add Props | Delete Props | Modify Values | Reconfigure |
|---|---|---|---|---|
| Normal Object | ā | ā | ā | ā |
preventExtensions() | ā | ā | ā | ā |
seal() | ā | ā | ā | ā |
freeze() | ā | ā | ā | ā |
Best Practices
1. Use Object.hasOwn() Instead of hasOwnProperty
// ā Good - Safe
if (Object.hasOwn(obj, 'prop')) {
}
// ā Avoid - Can break if hasOwnProperty is overridden
if (obj.hasOwnProperty('prop')) {
}
2. Use Object.assign() for Shallow Merging
// ā Good - Creates new object
const merged = Object.assign({}, defaults, userOptions);
// Alternative with spread (preferred for simple cases)
const merged = { ...defaults, ...userOptions };
3. Use Object.create(null) for Pure Dictionaries
// ā Good - No prototype pollution risks
const cache = Object.create(null);
cache['__proto__'] = 'value'; // Actually sets the property
// ā Risk - Prototype pollution
const cache = {};
cache['__proto__'] = 'malicious'; // Modifies prototype!
4. Use Object.freeze() for Constants
const CONFIG = Object.freeze({
API_URL: 'https://api.example.com',
TIMEOUT: 5000,
});
5. Use Object.fromEntries() for Transformations
// Filter object properties
const filtered = Object.fromEntries(
Object.entries(obj).filter(([key]) => !key.startsWith('_'))
);
// Transform values
const transformed = Object.fromEntries(
Object.entries(obj).map(([key, val]) => [key, val.toUpperCase()])
);
Files in This Section
- ā¢
README.md- This documentation - ā¢
examples.js- Runnable code examples - ā¢
exercises.js- Practice exercises with solutions
Navigation
- ā¢Previous: 7.3 Property Descriptors
- ā¢Next: 7.5 Prototypes
- ā¢Back to Module 7