WEBVTT

1
00:00:01.200 --> 00:00:02.510
Here's a student.

2
00:00:02.535 --> 00:00:09.848
You want a copy to work with, so you assign the student to a new variable and change the name on the copy to Thomas.

3
00:00:09.931 --> 00:00:13.214
The copy's name is Thomas, as you wanted.

4
00:00:13.356 --> 00:00:19.612
But the student's name is also Thomas now, and you never touched the student.

5
00:00:20.312 --> 00:00:24.211
To see why, let's start with what an object is.

6
00:00:24.341 --> 00:00:33.789
An object is a collection of data, which we call properties, and functions, which we call methods, in a single package.

7
00:00:33.930 --> 00:00:44.110
As an example, here's a student object, with a name, a favorite color, and a home address that is itself another object.

8
00:00:44.310 --> 00:00:47.849
There are two ways to access parts of an object.

9
00:00:48.048 --> 00:00:52.725
The first is dot notation, just like Java and Python.

10
00:00:53.110 --> 00:00:58.043
JavaScript also supports bracket notation, which is like an array.

11
00:00:58.242 --> 00:01:06.530
This approach is quite useful, and you need it when the name you want is held in a variable, or when it has a hyphen in it.

12
00:01:06.834 --> 00:01:10.222
You can add or delete a property at any time.

13
00:01:10.433 --> 00:01:19.394
When you ask for something that isn't there, JavaScript is permissive: you just get undefined, rather than an error.

14
00:01:19.594 --> 00:01:23.992
There is a wrinkle when you go more than one level at a time.

15
00:01:24.284 --> 00:01:30.076
The first access might return undefined, and the next step is an error.

16
00:01:30.368 --> 00:01:41.813
For example, ask for a number on a phone property that's not in the object, and you'll get a type error, because you're reading a property of undefined.

17
00:01:41.896 --> 00:01:51.148
The question mark dot operator can help, as it stops before that and returns undefined instead.

18
00:01:51.848 --> 00:01:55.039
Now for a point that often catches people.

19
00:01:55.180 --> 00:01:59.950
When you assign and change values, the behavior depends on the type.

20
00:02:00.091 --> 00:02:03.085
Numbers and strings are primitive types.

21
00:02:03.168 --> 00:02:07.542
Assign a number to a second variable, and you get a second value.

22
00:02:07.753 --> 00:02:12.581
Change one, and the other stays as it was.

23
00:02:12.781 --> 00:02:17.771
Objects, arrays and functions in JavaScript are reference types.

24
00:02:17.913 --> 00:02:21.939
Since they can be large, the variable doesn't hold the data.

25
00:02:22.243 --> 00:02:24.784
It holds a reference to the value.

26
00:02:24.995 --> 00:02:32.539
So assigning student to a second variable copies the reference to the object, and not the object itself.

27
00:02:32.750 --> 00:02:36.219
You now have two names for one object.

28
00:02:36.616 --> 00:02:41.084
Change the name through either one, and both see the change.

29
00:02:41.388 --> 00:02:44.102
That's what happened to our student.

30
00:02:44.303 --> 00:02:49.572
You might expect declaring the object with const to prevent this, but it doesn't.

31
00:02:49.713 --> 00:02:54.437
Const only stops the variable from being assigned a different value.

32
00:02:54.740 --> 00:02:58.082
The object it refers to can still change.

33
00:02:58.165 --> 00:03:01.948
If you want to stop that, use Object.freeze.

34
00:03:02.031 --> 00:03:07.300
Changes to a frozen object are ignored, or they're an error in strict mode.

35
00:03:07.511 --> 00:03:13.581
It only freezes the one level, though, so the address inside can still change.

36
00:03:14.282 --> 00:03:22.094
The differences between primitives and reference types are significant, and they even change what equal means.

37
00:03:22.490 --> 00:03:34.006
Even if two individual objects have the same contents, they are two distinct objects, so comparing them is false, with double equals or with triple equals.

38
00:03:34.089 --> 00:03:39.753
The comparison is true only when both variables refer to the same object.

39
00:03:40.056 --> 00:03:49.180
JavaScript has no operator that compares objects by their contents, though you could write a function to do this yourself if needed.

40
00:03:49.879 --> 00:03:53.929
The same reference type issues apply when you call a function.

41
00:03:54.233 --> 00:03:57.993
The parameter gets a copy of what the variable holds.

42
00:03:58.134 --> 00:04:06.689
For an object, that's a copy of the reference to the object, so the function can change the object, and the caller will see the change.

43
00:04:06.899 --> 00:04:12.644
You'll hear this called pass by reference, though the reference itself was copied.

44
00:04:12.948 --> 00:04:16.267
Compare this to when we pass a primitive type.

45
00:04:16.571 --> 00:04:21.457
If you change it in the function, the value isn't changed outside.

46
00:04:21.482 --> 00:04:23.279
This is pass by value.

47
00:04:23.421 --> 00:04:29.874
Note that even though a function can change an object's properties, it can't replace the caller's object.

48
00:04:30.178 --> 00:04:35.783
Assign a new object to the parameter, and only the local name changes.

49
00:04:36.483 --> 00:04:40.301
If you want a second object, you need to make a copy.

50
00:04:40.512 --> 00:04:47.232
The usual way to accomplish this is spread, three dots inside a new object literal.

51
00:04:47.373 --> 00:04:50.459
It copies each property into the new object.

52
00:04:50.600 --> 00:04:55.660
Change the copy's name, and you are just affecting the new object.

53
00:04:55.743 --> 00:04:58.934
The original object stays the same.

54
00:04:59.135 --> 00:05:00.619
But be careful.

55
00:05:00.830 --> 00:05:03.893
In our example, look at the address.

56
00:05:03.976 --> 00:05:08.827
That property held a reference, so the reference is what got copied.

57
00:05:09.224 --> 00:05:14.237
Change the city through the copy, and the original's city changes too.

58
00:05:14.634 --> 00:05:19.450
This is called a shallow copy, because it goes one level deep.

59
00:05:19.651 --> 00:05:23.028
For a deep copy, use structuredClone.

60
00:05:23.053 --> 00:05:25.628
It copies the nested objects too.

61
00:05:25.932 --> 00:05:31.747
It only works on data, though, and it throws an error on functions.

62
00:05:32.447 --> 00:05:35.011
You don't free objects yourself.

63
00:05:35.408 --> 00:05:43.010
JavaScript has a garbage collector, and an object stays as long as your program can reach it.

64
00:05:43.210 --> 00:05:47.875
Setting a variable to null can indicate you are done with something.

65
00:05:48.272 --> 00:05:53.878
When the last reference is gone, the object can be collected, and the memory freed.

66
00:05:54.274 --> 00:05:59.369
If you hold on to references you no longer need, you leak memory.

67
00:05:59.673 --> 00:06:05.476
In JavaScript we need to be especially careful with timers and event handlers.

68
00:06:06.176 --> 00:06:09.936
So when an object surprises you, follow the references.

69
00:06:10.077 --> 00:06:12.445
Who else is pointing at this object?

70
00:06:12.445 --> 00:06:15.532
Is this a copy, or another name?

71
00:06:15.732 --> 00:06:22.127
To explore these ideas further, try the playgrounds on the Objects and Arrays page.

72
00:06:22.338 --> 00:06:27.038
Methods, and the keyword this, get a film of their own.
