What Is The Difference Between Prototype-based Class Syntax And Class Syntax In JavaScript?
Solution 1:
The main differences between classes and constructor functions are:
Classes can’t be called without
new
, but functions intended as constructors can (and theirthis
will be wrong)'use strict'; function Foo() { console.log(this); } class Bar { constructor() { console.log(this); } } Foo(); Bar();
Classes can extend more types than constructors can (like functions and arrays)
'use strict'; function Foo(body) { Function.call(this, body); } Object.setPrototypeOf(Foo, Function); Foo.prototype = Object.create(Function.prototype); class Bar extends Function {} (new Bar('console.log(1)'))(); (new Foo('console.log(1)'))();
Classes’ prototypes are their parents (they inherit static properties); writers of constructor functions usually don’t bother with this
Non-classes can’t extend classes (because they can’t call the parent constructor – see the first point)
'use strict'; class Bar extends Function {} function Foo() { Bar.call(this); } Object.setPrototypeOf(Foo, Bar); Foo.prototype = Object.create(Bar.prototype); void new Foo();
Classes are also scoped like let
/const
(block scope, temporal dead zone, not redeclareable) rather than like var
(function scope, hoisted) or like function declarations (it’s complicated).
In your example, an additional difference is that sayHi
is defined by assigning to a new property instead of with e.g. Object.defineProperty
, so the property’s properties differ from those in the class example in that sayHi
is enumerable in the former but not the latter.
function UserA(name) {
this.name = name;
}
UserA.prototype.sayHi = function () {
alert(this.name);
};
class UserB {
constructor(name) {
this.name = name;
}
sayHi() {
alert(this.name);
}
}
let a = [];
let b = [];
for (let key in new UserA()) a.push(key);
for (let key in new UserB()) b.push(key);
console.log(a, b);
Solution 2:
From MDN:
JavaScript classes, introduced in ECMAScript 2015, are primarily syntactical sugar over JavaScript's existing prototype-based inheritance. The class syntax does not introduce a new object-oriented inheritance model to JavaScript.
You can use a tool like the Babel REPL to see how the ES6, class-based code you have above is then transpiled into ES5, prototype-based code:
ES6 Class
class User {
constructor(name) {
this.name = name;
}
sayHi() {
alert(this.name);
}
}
let user = new User("John");
user.sayHi();
Transpiled to ES5
"use strict";
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var User = function () {
function User(name) {
_classCallCheck(this, User);
this.name = name;
}
_createClass(User, [{
key: "sayHi",
value: function sayHi() {
alert(this.name);
}
}]);
return User;
}();
var user = new User("John");
user.sayHi();
All ES6+ functionality will be able to be transpiled into ES5-- it is all, effectively, syntactic sugar. All "new features" can still be achieved in ES5. This is called, I believe, the "One JavaScript" doctrine.
Post a Comment for "What Is The Difference Between Prototype-based Class Syntax And Class Syntax In JavaScript?"