user137717
user137717

Reputation: 2185

using closure to make private properties javascript

I have this prompt on code wars

"There's no such thing as private properties on a javascript object! But, maybe there are?

Implement a function createSecretHolder(secret) which accepts any value as secret and returns an object with ONLY two methods"

I'm pretty sure it wants me to use closures to achieve this and I have read about how to do this here:

Private variables and closures

https://developer.mozilla.org/en-US/Add-ons/SDK/Guides/Contributor_s_Guide/Private_Properties

This is my code:

function createSecretHolder(secret) {
  return {
    var _secret = secret;
    this.getSecret = function(){
      return _secret;
    }

    this.setSecret = function(secret){
      _secret = secret;
    }
  }
}

However, I get this error:

[eval]:6
 var _secret = secret;
              ^
SyntaxError: Unexpected token =
    at Object. ([eval]-wrapper:6:22)
    at 
    at evalScript (node.js:536:25)
    at startup (node.js:80:7)
    at node.js:906:3

I tried to make an object literal with a private value to hold the value of secret and mostly followed the examples from the sources I listed above. How do I create a closure with ONLY two methods to get and set data and where do I store the value of secret without adding another property?

Upvotes: 1

Views: 2524

Answers (3)

yoyoyojoe
yoyoyojoe

Reputation: 133

Using _ to prepend a property is a common naming convention JavaScript developers follow to show the intention that the property should not be altered, and it is definitely related to this prompt, but it seems like it is not hinting that it's needed and it may not be required for this challenge specifically.

The SyntaxError you're seeing is related to the _secret initialization being within the object literals rather than outside. Object literal syntax is different from variable declaration & assignment and should be mixed. You can move the var _secret = secret; to outside of and before the return statement (but still inside of the function createSecretHolder). (Super Hornet is right, but his code is missing the secret parameter, so his code would get a Reference error saying that secret is not defined.) While your attempt is slightly more declarative, you can actually do without the const _secret = secret. The first thing that the function does is to pair its argument with its parameter, in this case, declaring secret and assigning the input to it. So it is already "in closures".

Here's my take and it works almost the same, except I like to include the console.log() into my functions that I'm expecting to see a result.

function createSecretHolder(secret) {
  // input: secret 
  // output: object (with only 2 methods) 
  
  return {
    getSecret() { console.log(secret) },
    setSecret(input) { secret = input }
  }
}

const obj1 = createSecretHolder(5);
obj1.getSecret() // => 5
obj1.setSecret(2)
obj1.getSecret() // => 2

Same as:

function createSecretHolder2(secret) {
  return {
    getSecret() { return secret },
    setSecret(input) { secret = input }
  }
}

const obj2 = createSecretHolder2(91);
console.log(obj2.getSecret()) // => 91
console.log(obj2.setSecret(82)) // => undefined
obj2.setSecret('new Secret') // logs nothing, returns undefined
obj2.getSecret() // logs nothing, returns 'new Secret'

Upvotes: 0

thefourtheye
thefourtheye

Reputation: 239693

You are trying to return an object literal, in which you cannot have an assignment statement. To have the closure property, you need to store the variable in the function scope, like this

function createSecretHolder(secret) {
    var _secret = secret;

    return {
        getSecret: function() {
            return _secret;
        },

        setSecret: function(secret) {
            _secret = secret;
        }
    }
}

Now, _secret is in the scope of the getSecret and setSecret functions, because of the closure property. So they can access it.

Upvotes: 2

Super Hornet
Super Hornet

Reputation: 2907

The problem is return keyword actually returns object with a structure which you didn't follow. try this:

function createSecretHolder() {
  var _secret = secret;
return {

    getSecret : function(){
      return _secret;
    }
,
    setSecret : function(secret){
      _secret = secret;
    }
  }
}

Upvotes: 0

Related Questions