JavaScript: Everything about the Delete Operator

Learn how the delete operator deals with configurable and non-configurable properties, and much more.

Chidume Nnamdi 🔥💻🎵🎮
Bits and Pieces

--

Image by bluebudgie from Pixabay

The delete operator

According to ECMA Specification

Delete (O, P)

This is used to remove a specific own property of an object. It throws an exception if the property is not configurable.

The operation is called with arguments O and P where O is the object and P is the property key.

The delete operator is used to remove or delete property of an object:

const l = console.log
let obj = {
"d": 88
}
l(obj.d)
delete obj.d
l(obj.d)

We have an object obj with a property d whose value is 88. First, we log the value of the d property, it will output 88. Then, we remove the property with the delete operator, when we try to output the property it will display undefined

$ node delete
88
undefined

undefined is a primitive type in JS which means no value yet. The variable is defined but hasn’t been assigned a value. So when a property is deleted via the delete operator the value of the property returns undefined.

Tip: Share and reuse utility and UI components

Use Bit to easily publish, install and update small individual modules across different JavaScript projects. Don’t install entire libraries and don’t copy-paste code, when you can build faster with small reusable modules. Take a look.

Bit: Easily reuse and sync small modules and utils across JS projects

Non-configurable properties and delete

delete operator only works on configurable objects. delete cannot remove the non-configurable properties of an object.

Our obj object was configurable, that was why its property d could be removed. If we define the object non-configurable we won't be able to delete any of its properties

let obj = {
"d": 88
}
Object.defineProperty(obj, 'd', { configurable: false });l(obj.d)
delete obj.d
l(obj.d)
$ node delete
88
88

See, the output. The property wasn’t deleted. We used the Object#defineProperty method to make the d property non-configurable, setting configurable to false did the trick.

By default, properties in an object are set to be configurable.

let obj = {
"d": 88
}
l(Object.getOwnPropertyDescriptor(obj, "d"))$ node delete
{ value: 88,
writable: true,
enumerable: true,
configurable: true }

Then, if we use the Object#defineProperty method to set it to false, the property will become indelible to the delete operator.

var, let, const and delete

var, let and const declare non-configurable properties. So that’s why variables declared with var, let or const cannot be removed from the global scope.

const l = console.log
var f = 90
let g = 88
const h = 77
l("before delete f: " + f)
l("before delete g: " + g)
l("before delete h: " + h)
function func() {
let funh = 990
delete funh
l(funh)
delete f
delete g
delete h
l("inside func f:" + f)
l("inside func g:" + g)
l("inside func h:" + h)
}
func()
delete f
delete g
delete h
l("after delete f: " + f)
l("after delete g: " + g)
l("after delete h: " + h)

Output:

$ node delete
before delete f: 90
before delete g: 88
before delete h: 77
990
inside func f:90
inside func g:88
inside func h:77
after delete f: 90
after delete g: 88
after delete h: 77

See, all remained the same after a deletion with the delete operator.

functions and delete

functions cannot be deleted by the delete operator

function func() {
l("inside func")
}
delete func
func()

Output:

$ node delete
inside func

functions defined as an object property can be deleted.

var obj = {
d: function() {
l("inside obj d function")
}
}
obj.d()
delete obj.d
obj.d()

Output:

$ node delete
inside obj d function
delete.js:14
obj.d()
^
TypeError: obj.d is not a function

But when defined non-configurable, it cannot be deleted:

const obj = {
d: function() {
l("inside obj d function")
}
}
obj.d()
Object.defineProperty(obj, "d", { configurable: false })
delete obj.d
obj.d()

Output:

$ node delete
inside obj d function
inside obj d function

delete and the global scope

When we define a variable in the global scope without var, let or const:

f = 90

This variable f will be configurale:

f = 90
l(Object.getOwnPropertyDescriptor(global, "f"))

Output:

$ node delete
{ value: 90,
writable: true,
enumerable: true,
configurable: true }

so it can be deleted with the delete operator:

f = 90l(f)
delete f
l(f)

Output:

$ node delete
90
l(f)
^
ReferenceError: f is not defined

Oopss!! it throws a ReferenceError.

delete and local scope

delete does not affect local scopes and function scopes:

{
var g = 88
delete g
}
l(g)
function func() {
var funch = 90
delete funch
l(funch)
}
func()

Output:

$ node delete
88
90

delete and non-existent properties

If a non-existent property is passed to delete, it doesn’t throw an error. It just returns true.

var obj = {
"d": 90
}
l(delete obj.f)

Output:

$ node delete
true

delete and the prototype chain

delete in an object does not descend the prototype chain.

function Foo() {
this.bar = 90
}
Foo.prototype.bar = 88
var f = new Foo()

We have a bar in the own property bar of Foo and in the prototype property of the same name bar.

The bar in the Foo will be returned when referenced through its object:

f.bar // 90

When we delete the bar property:

...
delete f.bar

It only deletes the bar in the Foo, not in its prototype. So if we reference the bar again after the deletion the bar in the prototype will be returned.

...
l(f.bar)
delete f.bar
l(f.bar)

Output:

$ node delete
90
88

delete and JS built-in static properties

delete operator cannot remove static built-in properties of JS APIs like Array, Math, Object, Date etc.

l(delete Math.PI)

Output:

$ node delete
false

delete and its holey nature on Arrays

All types in JS inherits from the JSObject its C++ equivalent. Each property we define in Objects in JS is a member variable in the C++ JSObject.

obj = {
"d": 90,
"f": 88
}
JSObject {
d -> 90
f -> 88
}

Now, Arrays are JSObject too, the difference is that its content in the JSObject is not defined by the contents of the Array. They are defined by the number of contents.

obj = [90, 88]JSObject {
0: 90
1: 88
}

So that’s why we reference arrays by numbers obj[1]. The numbers are the properties like we have in objects.

In the obj array above it has two properties 0 and 1.

l(obj[0]) // 90
l(obj[1]) // 88

Like we did on objects with delete so we can too on arrays.

To delete the first element on obj, we do this:

delete obj[0]

This does remove the value 90

l(oj[0]) // undefined

But it does not reduce the number of the array.

l(obj.length) // 2
delete obj[0]
l(obj.length) // 2

See this leaves a hole in the array.

// obj
index: 0 1
[ , 88 ]

Even on objects, the delete operator does not remove the property, it only removes/deletes the value of the property leaving it undefined.

The hole in the array can be filled:

obj[0] = 100
l(obj[0]) // 100

Conclusion

We have seen what the delete operator does. Its effects on configurable and non-configurable elements. Its effects on global and local scope, its effects on Arrays holey elements.

With this, you will more comfortable and careful when using the delete operator in your JS apps.

If any questions, feel free to ask or drop me an email or DM.

Thanks!!!

Learn More

--

--

JS | Blockchain dev | Author of “Understanding JavaScript” and “Array Methods in JavaScript” - https://app.gumroad.com/chidumennamdi 📕