DEV Community

loading...
Cover image for 7 interesting deprecated JavaScript features

7 interesting deprecated JavaScript features

Nikola Stojaković
Software developer who loves philosophy and animals.
Originally published at nikolastojakovic.com ・4 min read

Since it’s birth 26 years ago at Netscape, JavaScript has come a long way. A language which was used only to interact with Java applets and do simple DOM manipulation is now used for writing back-ends and desktop and mobile applications too. Ecosystem grew by a big margin as well as the community. Just like every other language, JavaScript had (and still has) rough edges and quirks. We’re stuck with some of them because of the backward compatibility. Some are, (un)fortunately, mostly or completely gone. Some of these can still be used but it’s highly discouraged.
 

Object.prototype.watch and Object.prototype.unwatch methods

Unce upon a time there was an easy way to watch for the property changes on an object.

var cat = {};
cat.watch("name", function (propertyName, previousValue, newValue) {
  return "Mr. " + newValue;
});

cat.name = "Oswald";
console.log("Hello " + cat.name + "!"); // Hello Mr. Oswald!

cat.unwatch("name");

cat.name = "Luna";
console.log("Hello " + cat.name + "!"); // Hello Luna!
Enter fullscreen mode Exit fullscreen mode

Alternative

Nowadays you can use Proxy for this purpose.

const handler = {
  set: (obj, prop, value) => {
    if (prop === 'name') {
      obj[prop] = `Mr. ${value}`;
    }
  }
};

let cat = new Proxy({}, handler);

cat.name = "Oswald";
console.log("Hello " + cat.name + "!"); // Hello Mr. Oswald!

cat = { ..cat }; // this will remove behavior imposed by Proxy

cat.name = "Luna";
console.log("Hello " + cat.name + "!"); // Hello Luna!

Enter fullscreen mode Exit fullscreen mode

 

with statement

We all know how horrible working with long chain of properties can be. Fortunately, there is a way around it. Unfortunately – you shouldn’t use it.

const cat = {
  details: {
    passport: {
      location: {
        city: 'New York'
      }
    }
  }
};

with (cat.details.passport.location) {
  city = 'Meowyork';
}
Enter fullscreen mode Exit fullscreen mode

There are two reasons why you shouldn’t use with statement.

  • There is no place for optimization inside it, since you can’t predict if variable will refer to a property or to an outside variable.
  • It violates lexical scope, making program analysis very hard or even infeasible.

Also, it will be impossible for you to use it in ES6+ (or ES5 with the strict mode turned on). Strict mode prohibits it’s usage.

Alternative

The best you can do is to declare a variable which will hold the chain of properties instead.

const cat = {
  details: {
    passport: {
      location: {
        city: 'New York'
      }
    }
  }
};

const catLocation = cat.details.passport.location;
catLocation.city = 'Meowyork';
Enter fullscreen mode Exit fullscreen mode

 

Expression closures

Long before arrow functions were even in a plan, there were expression closures. They allowed you to omit curly braces and return statements from the method definitions completely.

var cat = function() "Luna";

var favorites = {
  food: function() "Tuna"
};
Enter fullscreen mode Exit fullscreen mode

Alternative

This has been removed in favor of using standard ES syntax.

var cat = function() { return "Luna"; }

var favorites = {
  food: function() { return "Tuna"; }
};
Enter fullscreen mode Exit fullscreen mode

Nowadays you can also use arrow functions and method definitions (both introduced in ES6).

const cat = () => "Luna";

const favorites = {
  get food() { return "Tuna"; }
};
Enter fullscreen mode Exit fullscreen mode

 

Object.observe and Object.unobserve methods

Back in the days there was also an easy way of getting an information about any changes to an object.

var cat = {
  name: "Oswald"
};

Object.observe(cat, function(changes) {
  console.log(changes);
});

cat.name = "Luna";
// [{ name: 'name', object: <obj>, type: 'update', oldValue: 'Oswald' }]

Object.unobserve(cat);

cat.name = "Max";
Enter fullscreen mode Exit fullscreen mode

There were the similar methods for arrays too – Array.observe and Array.unobserve.

Alternative

You can do this with Proxy too.

const cat = new Proxy({ name: "Oswald" }, {
  get: (target, prop) => {
    console.log({ type: "get", target, prop });
    return Reflect.get(target, prop);
  },
  set: (target, prop, value) => {
    console.log({ type: "set", target, prop, value });
    return Reflect.set(target, prop, value);
  }
});

cat.name = "Luna";
// { type: 'set', target: <obj>, prop: 'name', value: 'Luna' }

cat.name;
// { type: 'get', target: <obj>, prop: 'name' }
Enter fullscreen mode Exit fullscreen mode

 

let expressions and let blocks

In ES6, two statements for declaring block-scoped variables have been introduced; let and const. For the brief period of time, there were non-standard extensions to the let statement. These were let expressions and let blocks.

let blocks provided a way to instantiate a block where variables can have different values, without affecting the same-named ones outside of that block.

var catName = "Oswald";
var catAge = 2.5;

let (catName = "Luna", catAge = 2) {
  console.log(catName + "(" + catAge + " years old)"); // Luna (2 years old)
}

console.log(catName + "(" + catAge + " years old)"); // Oswald (2.5 years old)
Enter fullscreen mode Exit fullscreen mode

let expressions did the similar thing but on the expression level.

var catName = "Oswald";

let(catName = "Luna") console.log(catName); // Oswald

console.log(catName); // Luna
Enter fullscreen mode Exit fullscreen mode

Alternative

Since let is block scoped you can just declare variables again inside inner scope and change them there.

let catName = "Oswald";
let catAge = 2.5;

{
  let catName = "Luna", catAge = 2;
  console.log(catName + "(" + catAge + " years old)"); // Luna (2 years old)
}

console.log(catName + "(" + catAge + " years old)"); // Oswald (2.5 years old)
Enter fullscreen mode Exit fullscreen mode

 

HTML wrapper methods on strings

They are basically bunch of methods which wrapped your string with tags like bold, blink, font, small, big, i etc.

"Some teeny-tiny text".fontsize(3);    // <font size="3">Some teeny-tiny text.</font>
"Some tiny text.".small();             // <small>Some tiny text.</small>
"Some yuuuge text.".big();             // <big>Some yuuge text.</big>
"Talk to the hand!".bold();            // <b>Talk to the hand!</b>
"You have been terminated.".blink();   // <blink>You have been terminated.</blink>
Enter fullscreen mode Exit fullscreen mode

Alternative

There are no alternatives for this monstrosity.
 

ParallelArray

This one was an experimental feature introduced by Mozilla in the Firefox (specifically, version 17 of the Gecko engine). It’s purpose was to enable data-parallelism by executing multiple functions in parallel. If it wasn’t possible, they would be executed in the sequential order.

var cats = new ParallelArray(["Oswald", "Luna", "Max"]);
cats.map(function(name) {
  return "😸 " + cat;
});
Enter fullscreen mode Exit fullscreen mode

Alternative

Today you can use Promise.all to accomplish this.
 

Conclusion

It’s fantastic to see how much JavaScript has progressed for the last 26 years. Who could’ve thought that language made in 10 days can become one of the most dominant in the industry? I believe it’s a good practice to take a step back and see how things worked in the past. That can teach us not to repeat the same mistakes anymore. It can also make us more grateful for the things we have today. Even though I have a fair share of criticism for JavaScript, I can’t wait to see what’s coming in the next two decades.

Discussion (21)

Collapse
jfbrennan profile image
Jordan Brennan

Awesome!

Minor improvement to the with alternative could be:

const cat = {
  details: {
    passport: {
      location: {
        city: 'New York'
      }
    }
  }
};

const {location} = cat.details.passport; // Add optional chaining if you didn't define cat
location.city = 'Meowyork';
Enter fullscreen mode Exit fullscreen mode
Collapse
stojakovic99 profile image
Nikola Stojaković Author • Edited

Yup, that's another way of doing it - although that will return

Uncaught SyntaxError: redeclaration of non-configurable global property location
Enter fullscreen mode Exit fullscreen mode

in the browser since location is a global property - we can rename it to something else though.

Collapse
jfbrennan profile image
Jordan Brennan

True, but only at the global scope. Safe inside any other scope

Collapse
bugb profile image
bugb • Edited

Some example with with

with(Math){max(1,2)}
Enter fullscreen mode Exit fullscreen mode

To watch Object change, you can also Object.defineProperty

var o = {};
var bValue = 38;
Object.defineProperty(o, 'b', {,
  get() { console.log("Inside Get"); return bValue; },
  set(newValue) { console.log("Inside Set"); bValue = newValue; },
  enumerable: true,
  configurable: true
});
o.b=12
o.b
Enter fullscreen mode Exit fullscreen mode
Collapse
miketalbot profile image
Mike Talbot

Great list, I didn't have a clue about some of those :)

One other way of doing a "with like thing" having a go at the C# syntax I've seen is this:


function scope(value, fn) {
    return fn(value)
}

const cat = {
    details: {
        passport: {
            location: {
                city: "New York"
            }
        }
    }
}

scope(cat.details.passport.location, _ => {
    _.city = "Meowyork"
})
Enter fullscreen mode Exit fullscreen mode
Collapse
stojakovic99 profile image
Nikola Stojaković Author

That's nice!

Collapse
lionelrowe profile image
lionel-rowe • Edited

Don't forget let and const are already block scoped, so a simple alternative to your let block example is this:

let catName = 'Oswald'
let catAge = 2.5

{
    let catName = 'Luna', catAge = 2
    console.log(`${catName} (${catAge} years old)`) // Luna (2 years old)
}

console.log(`${catName} (${catAge} years old)`) // Oswald (2.5 years old)
Enter fullscreen mode Exit fullscreen mode
Collapse
stojakovic99 profile image
Nikola Stojaković Author

You're right, thanks - I'll update the article now.

Collapse
lukeshiru profile image
LUKESHIRU

Nice article, Nikola!

I didn't knew those let blocks :O ... and I actually laugh with your "alternatives" for "HTML wrapper methods on strings".

Thanks for sharing!

Collapse
stojakovic99 profile image
Nikola Stojaković Author

Glad you liked it!

Collapse
krtirtho profile image
KR Tirtho

I've to say JavaScript changed so much that its hard to keep track of what have changes... But Proxy thing is just blew my mind. I never knew it was available. Thanks a lot

Collapse
triptych profile image
Andrew Wooldridge

Thanks! This was very informative.

Collapse
ki1t3ty profile image
Ki1t3ty

great post thanks .

Collapse
tojacob profile image
Jacob Samuel G.

👍🏽

Collapse
shalvah profile image
Shalvah

Awesome article!

Collapse
hyggedev profile image
Chris Hansen

HTML wrapper methods on strings: "There are no alternatives for this monstrosity." Hahah 🤣 Wow, never knew they even exist tbh. Great stuff, thanks!

Collapse
michaelprimo profile image
Michael Primo

I only knew about with, which is used sometimes on code golfing 🙂 Nice article!

Collapse
nombrekeff profile image
Keff

Nice post! Some of those are obscure, did not now a couple of them

Collapse
eidellev profile image
Lev Eidelman Nagar

Great post! I thought 'with' was a fever dream from my teenage years.

Collapse
stojakovic99 profile image
Nikola Stojaković Author

You're welcome!