Why does a closured function not protect the values of an object but a naked function will?

StackOverflow https://stackoverflow.com/questions/22239592

  •  10-06-2023
  •  | 
  •  

Pregunta

Why does a closured function not protect the values of an object but a naked function will? I have the below code on jsFiddle.

I'm using Lo-Dash _.assign function with a default Object. Like so:

var cnst = _.constant({test: 'It Works!'})
var newCnst = _.assign(cnst(), {test: "It doesn't work!"})
console.log(cnst())
console.log(newCnst)

Which results in:

{test: "It doesn't work!"}
{test: "It doesn't work!"}

So I just do a naked constant function like so:

var test = function(){return {test: 'It Works!'}}
var newTest = _.assign(test(), {test: "It doesn't work!"})
console.log(test())
console.log(newTest)

Which results in:

{test: 'It Works!'}
{test: "It doesn't work!"}

Just like it should. Why is the closured constant value not protected? Even when I do it myself:

var constant = function(value){return function(){return value}}
var t = constant({test: 'Closured Works!'})
var t2 = _.assign(t(), {test: "No closured doesn't work!"})
console.log(t())
console.log(t2)

Which results in:

{test: "No closured doesn't work!"}
{test: "No closured doesn't work!"}
¿Fue útil?

Solución

The reason is that in both the Lo-Dash example and in custom constant implementation, the function created always returns a reference to the same instance. That is to say, in both these snippets only one object is ever created:

var cnst = _.constant({test: 'It Works!'})

var constant = function(value){return function(){return value}}
var t = constant({test: 'Closured Works!'})

This can be confirmed by checking:

console.log(newCnst === cnst()) // true
console.log(t2 === t())         // true

However, in this example:

var test = function(){return {test: 'It Works!'}}

A new object is created every time the function is called. So when you call:

var newTest = _.assign(test() /* new object created here */, {test: "It doesn't work!"})
console.log(test() /* new object created here */)
console.log(newTest)

This can be confirmed by checking:

console.log(newTest === test()) // false
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top