Objects Flashcards

1
Q

Are object keys sorted? If so how?

A

Integer keys are sorted by value. String keys are sorted by order of creation

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Are objects passed by value or reference? What about primitives?

A

Primitives are passed by value. Objects are passed by reference

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

How to deeply copy an object?

A

If the object is a data object, i.e. no methods, then the built-in structuredClone() method will do the job. Otherwise, we would need to use some library like lodash

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

How does garbage collection work?

A

The key idea is ‘reachability’. First javascript has some roots, which are a base set of inherently reachable values. E.g. Execution context and global variables. Any other value is considered reachable only if it is reachable from some root.
For example:
1. let user = { … }; user = null
2. let user1 = { … }; let user2 = user1; user1 = null;
For (1) the object literal will be garbage collected since it is unreachable. For (2) since the object literal is reachable by user2, we cannot garbage collect it.
NOTE: Only incoming edges matter when determining if an object is reachable.

Then the basic algorithm is to mark and sweep nodes.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

function marry(man, woman) {
woman.husband = man;
man.wife = woman;

return {
father: man,
mother: woman
}
}

let family = marry({
name: “John”
}, {
name: “Ann”
});

delete family.father;
delete family.mother.husband;

Is there any garbage collection that will take place?

A

https://www.notion.so/wesleylim/Javascript-02c81e242b5e4da29c10541c66677a32?pvs=4#e6f19c05a3c145188405ef34942e9c2b

Yes. As seen in the diagram above, we have a ‘family’ variable that points to an object. The object is connected to two objects via ‘father’ and ‘mother’. The objects also point to each other via ‘man’ and ‘wife’. Thus (1) deletes the link between the root object and the ‘father’ object, while (2) deletes the link between the ‘mother’ object and the ‘father’ object, so now the ‘father’ object is unreachable.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Is the following valid code? If so, why?

function sayHi() {
alert( this.name );
}

A

Yes. The value of ‘this’ is evaluated during the run-time, depending on the context.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

What is the value of ‘this’ in the following code?

function sayHi() {
alert( this.name );
}
sayHi();

A

If strict mode it will be undefined.
In non-strict mode it will the value of the global object, which is ‘window’ in a browser.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

What is the value of ‘this’ in the following code?

let user = {
firstName: “Ilya”,
sayHi() {
let arrow = () => alert(this.firstName);
arrow();
}
};
user.sayHi();

A

It is the ‘user’ object. Arrow functions do not have their own ‘this’ value, and instead take it from the surrounding lexical scope which it is defined.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

What is the output of the following code, if any?

let group = {
title: “Our Group”,
students: [“John”, “Pete”, “Alice”],

showList() {
this.students.forEach(function(student) {
alert(this.title + ‘: ‘ + student);
});
}
};

group.showList();

A

There will be an error because the ‘this’ value in the callback that is passed to the .forEach() method, is undefined.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

What are constructor (functions) and what happens when you call them with ‘new’?

A

Constructor functions are just regular functions that should only be called with ‘new’ and are named Uppercase by convention.
When functions are executed with new:
1. An empty object is created and assign to ‘this’
2. The function body executes, usually assigning properties to ‘this’
3. The value of ‘this’ is returned.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

What are symbols, and what are they used for?

A

By specification, only two primitive types may serve as object property keys: strings or symbols.
A “symbol” represents a unique identifier.

let id1 = Symbol(“id”);
let id2 = Symbol(“id”);
alert(id1 == id2); // false

Symbols allow us to create “hidden” properties of an object, that no other part of code can accidentally access or overwrite. For example, when working with data objects from third party libraries, we might used a symbol instead of string to prevent potentially overriding properties defined by the library. They are skipped in a for-in loop.

If we need to define global symbols we can instead create them like so:
let globalSymbol = Symbol.for(‘id’); // created if not already created
let anotherSymbol = Symbol.for(‘id) // references created symol.
console.asset(globalSymbol=== anotherSymbol) // true

We can also get back the key used to create a symbol using the Symbol.keyFor(symbol) method.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

How are objects casted to primitives(whether implicitly or explicitly)?

A

Different scenarios expect different types of values, called hints = ‘string’ | ‘number’ | ‘default’(rare case when operator is not sure what to expect)
To do the conversion, JavaScript tries to find and call three object methods:
1. Call objSymbol.toPrimitive – the method with the symbolic key Symbol.toPrimitive (system symbol), if such method exists,
2. Otherwise if hint is “string”, try calling obj.toString() or obj.valueOf(), whatever exists.
3. Otherwise if hint is “number” or “default”, try calling obj.valueOf() or obj.toString(), whatever exists.

let user = {
  name: "John",
  money: 1000,

  [Symbol.toPrimitive](hint) {
    alert(`hint: ${hint}`);
    return hint == "string" ? `{name: "${this.name}"}` : this.money;
  }
};

// conversions demo:
alert(user); // hint: string -> {name: "John"}
alert(+user); // hint: number -> 1000
alert(user + 500); // hint: default -> 1500
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

What are Property Flags

A

Objects have properties. Properties have flags that are used to configure them:
0. value (default, not configurable)
1. writable - if true -> value can be modified
2. enumerable - if true -> listed in loops
3. configurable - if true, the property can be deleted and flags can be modified.

When a property is created, all three flags are true.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

How do you access property flags? How do you modify them?

A

Access:
Use the Object.getOwnPropertyDescriptor(obj, propName) method that returns the four flags for a property as an object.
If we need to get many properties’ descriptors in one function call we can use Object.getOwnPropertyDescriptors(obj)

Modify
We can use the Object.defineProperty(obj, propName, Partial<PropertyDescriptor>) method which defines the property on the object with the descriptor passed in. Importantly, flags not defined in the descriptor object passed in are default false.
If we need to define many properties' descriptors in one function call we can use Object.defineProperties(obj, Record<propName, descriptor>)</PropertyDescriptor>

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Given that the schema of an object User looks like:
{
_id: 01ascnhyawdm7126b$21
name: ‘wesley’,
email: ‘wesley_lim@hive.gov.sg’,
}

Can you explain why it might be that Object.keys(user) only returns name and email?

A

This is likely because the property has its ‘enumerable’ flag set to false, so it does not appear in iterative functions like keys() and for loops.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

What is the ‘configurable’ property flag, and what happens if it is false.

A

When a property’s descriptor has ‘configurable: false’ there are a few implications:
1. You cannot set configurable: true again, even with Object.defineProperty()
2. It prevents changes to property flags and their deletion. The only exception is value is allowed to change.

17
Q

Assuming the object is not nested, is the following a good way of cloning an object?

for (let key in user) {
clone[key] = user[key]
}

A

No for two reasons:
1. This copy is not flag-aware. If we want to copy properties AND their flags then we do:
let clone = Object.defineProperties({}, Object.getOwnPropertyDescriptors(obj

  1. for(… in) loops ignore symbolic and non-enumerable properties. If we wanted all properties, we can use Object.getOwnPropertyDescriptors() which returns Record<propName, Descriptor)
18
Q

How do I ‘seal’ an object property?
What about sealing objects?

A

Sealing properties:
You can set the property with a descriptor { writable: false, configurable: false }.

Sealing objects:
1. Object.freeze() - prevents add/remove/change by setting Configurable: false, writable: false
2. Object.seal() - prevent add/remove by setting Congurable: false
3. Object.preventExtensions() - prevent adding new properties

19
Q

What are getters and setters? Why might we use them

A

Objects have two kinds of properties, data props and accessor props. Getters and setters are accessor props defined by ‘get’ and ‘set’ keywords. They allow customizing the behavior of getting and setting a property.

The motivation of accessors is similar to decorators:
To wrap the original property values with some logic(e.g. input validation).
It is also for encapsulation and abstraction, e.g. fullName is made out of name and surname.
Finally, it also helps to ensure backward compatibility: if we use getters and setters to interact with an object, it’s okay if the internal state of the object changes(E.g. remove property)

let user = {
  name: "John",
  surname: "Smith",

  get fullName() {
    return `${this.name} ${this.surname}`;
  },

  set fullName(value) {
    if (!this.isValidFullName) {
        throw new Error('fullName must be a string of more than 3 characters")
    }
    [this.name, this.surname] = value.split(" ");
  }
};

user.fullName = 'Jacob'
console.log(user.fullName) // Jacob
20
Q

How do accessor descriptors differ from property descriptors?

A

Instead of ‘value’ and ‘writable’ the descriptor has ‘get’ and ‘set’.
Note that a property can be either an accessor (has get/set methods) or a data property (has a value), not both.