2

i created a crypto object as follows:

var crypto = {
  encrypt: function(s) {

  }
};

crypto.encrypt("cat");

I would get the following error

Uncaught TypeError: crypto.encrypt is not a function

var crypt = {
  encrypt: function(s) {

  }
};

crypt.encrypt("cat");

this would work. I realized that there is already an inbuilt crypto object so the crypto object i defined was not being recognized.

My understanding is that the variables declared later will shadow variable declared previously.

For example when i create two objects like follows:

var test = {
  testing2: function() {
    return "there";
  }
}

var test = {
  testing: function() {
    return "hey";
  }
}

test.testing2()

and i call test.testing2() then the similar error is thrown because the second test variable has shadowed the first. So if variable shadowing works with self created variables then why is crypto not being shadowed? Is it the case that the predefined objects are always higher in priority so any self created objects will not shadow the window objects. I appreciate any insights into this. Thanks!

adiga
  • 34,372
  • 9
  • 61
  • 83
kofhearts
  • 3,607
  • 8
  • 46
  • 79

1 Answers1

6

Usually, yes, variables declared later (with var) will simply overwrite vars declared earlier with the same name. The difference is that variables declared with var on the top level assign to window properties, and window.crypto is a property with a getter, but no setter:

console.log(
  Object.getOwnPropertyDescriptor(window, 'crypto')
);

So when you assign to window.crypto with var crypto, there's no setter, so nothing happens. Many other window properties behave the same way.

Consider using const or let instead:

const crypto = {

  encrypt: function(s) {

  }
};

crypto.encrypt("cat");

Or put it into an IIFE:

(() => {
  var crypto = {

    encrypt: function(s) {

    }
  };

  crypto.encrypt("cat");
})();

Or use a linter

You can also use use strict to make the error explicit:

'use strict';
var crypto = {

  encrypt: function(s) {

  }
};

console.log('successfully defined crypto');
crypto.encrypt("cat");
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • thanks. i am still confused why using let instead of var solved the problem. Even by using let we are still at the top level so why doesnt it conflict with the window crypto. I understand that let is block scoped and var is function scoped. can we assume the javascript code that we write to be inside a block { } so that any let declarations are in this scope. Thanks for help! – kofhearts Jul 01 '19 at 05:18
  • That's just how `const` and `let` work - they don't assign to properties on `window`, unlike `var`, even if on the top level. – CertainPerformance Jul 01 '19 at 05:29
  • i see. so is var outdated. should we always use let? what do you say? and seems like with the introduction of let, iffe is also outdated. what is your opinion? – kofhearts Jul 01 '19 at 05:34
  • Yes, I would definitely consider `var` outdated - there's almost no reason to use it in modern code. It has too many gotchas. Use a transpiler like Babel to transpile down to ES5 if you need compatibility with obsolete browsers. IIFEs aren't outdated, though - they're a very common pattern, and have many useful uses. *Some* might say that they're *somewhat* obsolete if you're using a module system, which is true to an extent, but not entirely, IMO – CertainPerformance Jul 01 '19 at 05:36