How to create simple Angular signal() in JS
Tags: angular, javascript, webdev, beginners
Published: 2023-08-02 10:06:43

Hey there!

So recently I was playing with Angular signals and noticed that I didn't really understand how exactly this language construction works:

```ts
public counter = signal(0);

// Then you use it like that in the template.

{{ counter() }}

// But also work with it like that:

counter.update((count) => count + 1)
```

Although I've been working with JS for years, for some reason I'd never seen such a way to use functions before until I tried signals.

This is pretty basic JS functionality, and I will show you in super simple example how exactly it works.

## You'll learn
- What JS functions really are
- How angular signals are implemented

## JS Functions

So a quick note: functions in JS are not exactly functions; they are function-objects. Functions are objects with internal, hidden **[[Call]]** and **[[Contruct]]** methods, and they basically make an object a function.

But it is still an object, and this is exactly how we can achieve the functionality that we have in signals.

I think it's a rather interesting feature of the language. But I am generally ok with any weirdness (that JS supplies in huge volumes), so you can draw your own conclusions.

## Implementing signal

We are not going to dive deep into how exactly angular signals are _really_ implemented, but we'll create very simple, basic functionality for them. First, we just create a function:

```js
function signal(value) {

}
```

To make it look exactly like an angular signal. As you remember, we put signal into a variable by calling it like that:

```js
const counter = signal(0);
```

And after that, we can either call **counter** or update it. That means we, for first, should make the **signal** function return another function:

```js
function signal(value) {
  function caller() {
    return value;
  }
  
  return caller;
}
```

I called it **caller** for whatever reason that popped up in my mind at the moment of writing that code. And now the final stroke: using the nature of JS function objects to make **counter** have mixed behavior:

```js
function signal(value) {
  function caller() {
    return value;
  }
  
  caller.set = (newValue) => value = newValue;
  caller.update = (fn) => value = fn(value);
  
  return caller;
}
```

And here we are, utilizing the hybrid nature of JS functions.

You can see that we are clearly assigning properties to the **caller** function as if it were an object.

We've added **set** and **update** callbacks to the **caller** function. Now, when the signal is initialized, we always have the option to call those callbacks or the signal itself.

- **set** method allows direct updating of the value.
- **update** method lets us do the same but using a callback, passed as a parameter.


```js 
// getting the signal value
counter();

// updating signal value
counter.set(42);
// or
counter.update(c => c + 1);
```

---

Angular Signals is a very powerful and well-thought-out interface; it is much more complicated and flexible, than our implementation. But it still uses a similar approach because there is always a limiting factor in language possibilities.

However, now you know how to utilize the hybrid nature of JS functions in your everyday routine.

Hopefully you learned something new and it was helpful.

Thank you!