Concat and This

Delving into JavaScript I

Resource: JS Is Weird is a quiz, mostly to do with type conversion, on the strange things that happen in Javascript

Resource: JSFuck shows that any code in Javascript can be written in just 6 characters

Use of: concat

What happens when concatenating with values and arrays?

CodeResultWhat is happening?
[].concat(1)[1]Add a value to an empty array
[].concat(1,2)[1,2]Add multiple values to an empty array
[1].concat(2)[1,2]Add a value to a non-empty array
[1].concat(2,3)[1,2,3]Add a value to a non-empty array
[].concat`1` ['1']Add a value using backticks to an empty array
[].concat([])[]Add an empty array to an empty array
[].concat([[]])[[]]Add a nested array to an empty array

But .push() will take an argument, whether a value or array, and add it as a singular element to an array. To add elements of an array individually, destructure.

console.log(...[...[1], 2])
>> 1 2

Use of: this

const a = {
    val: 1,
    get: function() { return this.val }
}
console.log(a.get() === a.val)
>> true

const b = {
    val: 1,
    get() { return this.val }
}
console.log(b.get() === b.val)
>> true

Using arrow functions will return undefined. While arrow functions returned from closures can retain a context, in objects, arrow functions cannot access adjacent properties.

Trying to access a value using this in a later value will not work anymore. I could have sworn at one point that it used to, need to look up some of my old code.

Note:
- Test in Weak/Map and Weak/Set
- Retroactive use of object access and declaration

Factory
Creates objects of given properties

const factory = (val = 1) => ({
    get() { return this.val || val },
    set(v) { this.val = v }
})
const value = factory()
console.log(value.get())
>> 1
value.set(2)
console.log(value.get())
>> 2

Default value provided. Created instances use the given value from the context of origin until a property has been set to override it.

Constructors

const ConstructorA = function(val = 1) {
    this.__val = val
}
ConstructorA.prototype.get = function() { return this.__val }
ConstructorA.prototype.set = function(val) { this.__val = val }

const a = new ConstructorA()
console.log(a.get())
>> 1
a.set(2)
console.log(a.get())
>> 2

function ConstructorB(val = 1) {
    this.__val = val
}
ConstructorB.prototype.get = function() { 
    const { __val: val } = this
    return val
}
ConstructorB.prototype.set = function(val) { this.__val = val }

const b = new ConstructorB()
console.log(b.get())
>> 1
b.set(2)
console.log(b.get())
>> 2

class ConstructorC {
    constructor(val = 1) { this.__val = val }
    get() { return this.__val }
    set(val) { this.__val = val } 
}

const c = new ConstructorC()
console.log(c.get())
>> 1
c.set(2)
console.log(c.get())
>> 2

Like objects, constructors cannot use arrow functions to access their values. Classes are syntactic sugar for creating prototypes. The difference is syntactic and semantic, mainly the explicit use of constructor keyword, as well as static and private fields.

Note:
- Create access functions in function constructors

The use of static methods can easily be replicated by global variables.

const Constructor = function(val) { this.__val = val }
Constructor.prototype.get = function() { return this.__val }
Constructor.prototype.set = function(val) { this.__val = val }

Constructor.of = (val = 1) => new Constructor(val)

const obj = Constructor.of()
console.log(obj.get())
>> 1
obj.set(2)
console.log(obj.get())
>> 2

Quick Note on Variables

[no keyword]
- global
- hoists variable
- can be redeclared and reassigned
- must be defined (assigned a value) when declared
- legacy

var
- hoists variable
- can be redeclared and reassigned
- legacy

let
- mutable
- cannot be redeclared
- can be reassigned
- supported in all browsers since 2015

const
- immutable primitives
- mutable properties and content of objects
- cannot be redeclared or reassigned
- supported in all browsers since 2015