How to prevent modification of an object in Javascript and prevent them from being accessible in the console

How to prevent modification of an object in Javascript and prevent them from being accessible in the console

There are many ways to lock an object according to your needs. The Object object (despite the redundancy), has some useful functions that will allow you to lock objects.

  • Object.freeze
  • Object.seal
  • Object.preventExtensions

For all the examples in this post, we'll use the following object :

var myBankAccount = {
    user: {
        fullname : "Bruce wayne",
        age: 26,
        occupation: {
            day: "Philanthropist billionaire",
            night: "I'm Batman"
        }
    },
    multipleAccounts: true,
    accounts : [
        {
            money: (9999999999999999),
            currency : "EUR"
        },
        {
            money: (9999999999999999),
            currency : "USD"
        }
    ]
};

Object.freeze

Freeze method freezes an object (thanks captain obvious).

This method prevents new properties from being added to it, prevent existing properties from being removed and prevents existing properties (or their enumerability, configurability, or writability) from being changed. In essence the object is made immutable. The method returns the frozen object.

// Add a property before being frozen
myBankAccount.bankName = "Gotham Merchant Bank";

// Shows the value in the object as the property
// was created before the object has been frozen
console.log(myBankAccount.bankName);

// Freeze the object
Object.freeze(myBankAccount);
/**
 * Now the object cannot be modified, deleted written
 */
myBankAccount.flushMethod = function(){
  SendAllMoneyToJokerAccount();
};

// Will be neither deleted !
delete myBankAccount.bankName;

// Throws error, method doesn't exist.
myBankAccount.flushMethod();

Note that you freeze only the object as first parameter. If a value of the frozen object is an object it can still be modified, unless you freeze them too. If you try to modify myBankAccount.user , you'll be able to add properties inside of that object.

// Freeze object
Object.freeze(myBankAccount);

// The user property is an object, and you didn't freeze it Too
// to solve use Object.freeze(myBankAccount.user)
myBankAccount.user.flushMethod = function(){
    SendAllMoneyToJokerAccount();
};

// Money succesfully transfered :(
// You disappoint Batman
myBankAccount.user.flushMethod();

Object.preventExtensions

The preventExtensions method prevents new properties from ever being added to an object (i.e. prevents future extensions to the object).

// Add property before being nonExtensible
myBankAccount.newValue = 12;

// Disallow new properties to the bank account
Object.preventExtensions(myBankAccount);

// Silently ignored or TypeError
myBankAccount.flushAccount = function(){
   sendMoneyToJokerAccount();
};

console.log(myBankAccount.newValue);// Output :12

// Method doesn't exist
myBankAccount.flushAccount();

Object.seal

Seal method seals an object, preventing new properties from being added to it and marking all existing properties as non-configurable. Values of present properties can still be changed as long as they are writable.

// Seal object
Object.seal(myBankAccount);

// Changing property values on a sealed object still works.
myBankAccount.multipleAccounts = false;

// But you can't convert data properties to accessors, or vice versa.
Object.defineProperty(myBankAccount, 'foo', { get: function() { return 'hey'; } }); // throws a TypeError

delete myBankAccount.user; // throws a TypeError 
myBankAccount.newPropertyToAdd = 'qwe'; // throws a TypeError

Quick comparison and notes

Function Object is made non-extensible configurable is set to false for each property
Object.preventExtensions Yes No
Object.seal Yes Yes
Object.freeze Yes Yes
  • The subobjects of a frozen object are modifiables unless you freeze them.
  • The prototype chain using Object.seal remains untouched. However, the __proto__ property is sealed as well.
  • Properties can still be added to the object prototype. However, calling preventExtensions on an object will also prevent extensions on its __proto__ property.

The Object variable has useful method to check if any of the previous functions has been used on an object :

  • Object.isFrozen(myObj).
  • Object.isSealed(myObj).
  • Object.isExtensible(myObj).

Unless you're working with strict mode in your code ('use strict';) no errors will be thrown in the console as everything will be silently ignored. However in strict mode, you'll get Type Errors if you try to accomplish task as add a property in a non extensible object etc.

Prevent a variable from being accesible in the console

If you're scared that someone could check out your code and modify things in the console, just wrap your code inside an anonymous function. That will prevent from appearing in the console, so other developer wouldn't be able to access the code that way.

Analize the following code :

<input type="button" id="transfer" value="TransferToAccount" />
<input type="text" id="account" />
<input type="text" id="ammount" />

<script>
var allow_transaction = false;
var MySuperBankObject = {
    person: "Bruce",
    account: 123123,
    money: (9999.99),
    sendMoneyToAccount : function(idAccount,amount){
        if(amount <= this.money){
            allow_transaction = true;
            TransferToAccount(this.account,idAccount,amount);
        }else{
            throw new Error("Too much money. You don't have all that money :(.");
        }
    }
};

function TransferToAccount(source_account,target_account,amount){
    if(!allow_transaction){
        throw new Error("The transaction needs to be verified");
    }

    console.log(amount + " Dollars succesfully transfered to " + target_account + " account from "+ source_account);
}

// Onclick, do transaction
document.getElementById("transfer").addEventListener("click",function(){
    // get required info
    var amount = document.getElementById("amount").value;
    var accountTarget = document.getElementById("account").value;
    // Do transaction 
    MySuperBankObject.sendMoneyToAccount(parseInt(accountTarget),parseFloat(amount));
},false);
</script>

If you include this code inside your document, and someone decides to read the code of that files, they could find and execute the following in the console because MySuperBankObject object is exposed globally : 

Prevent variable from being accesed in console

And nobody wants that, do you? To prevent this, (although the code can be visible in the browser, it can't be modified) wrap the previous code in an anonymous function:

(function(){
   /**
    * All the code that needs to be unexposed in the console here.
    */
})(); // Send parameters inside the function if you need to

Now wrap the previous inside an anonymous function :

<input type="button" id="transfer" value="TransferToAccount" />
<input type="text" id="account" />
<input type="text" id="ammount" />

<script>
(function(){

var allow_transaction = false;
var MySuperBankObject = {
    person: "Bruce",
    account: 123123,
....
....

})();
</script>

Useful isn't? If a developer try to get mySuperBankObject in the console, he'll face that :

not defined console

The code will work as expected, but the variables are not exposed in the console anymore. Note too that the code still being readable by a developer, although can't be modified easily it stills being modified if your code has weak points (getters and setter misconfigured i.e a stupid global function as getMySuperBankObject ...) and with the enough knowledge. Minify your code to decrease the readability.

Finally, please don't handle a bank account with some code like the posted in this post, thanks !.

Have fun

This could interest you

Become a more social person