这些可互换的语法是否可以创建JS类?我已经习惯了class
语法,但并不完全理解它们之间的差异。
function User(name) {
this.name = name;
}
User.prototype.sayHi = function() {
alert(this.name);
}
let user = new User("John");
user.sayHi();
VS。
class User {
constructor(name) {
this.name = name;
}
sayHi() {
alert(this.name);
}
}
let user = new User("John");
user.sayHi();
答案 0 :(得分:2)
类和构造函数之间的主要区别是:
不能在没有new
的情况下调用类,但是作为构造函数的函数可以(并且它们的this
将是错误的)
'use strict';
function Foo() {
console.log(this);
}
class Bar {
constructor() {
console.log(this);
}
}
Foo();
Bar();
类可以扩展比构造函数更多的类型(如函数和数组)
'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的原型是他们的父母(他们继承静态属性);构造函数的编写者通常不会打扰这个
非类不能扩展类(因为它们无法调用父构造函数 - 请参阅第一点)
'use strict';
class Bar extends Function {}
function Foo() {
Bar.call(this);
}
Object.setPrototypeOf(Foo, Bar);
Foo.prototype = Object.create(Bar.prototype);
void new Foo();
类的范围也类似于let
/ const
(块范围,临时死区,不可重新声明),而不是类似var
(函数范围,已提升)或类似函数声明(它是复杂)。
在您的示例中,另一个区别是sayHi
是通过分配给新属性而非使用例如Object.defineProperty
,因此属性的属性与类示例中的属性不同,sayHi
在前者中是可枚举的,而在后者中则不是。
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);
答案 1 :(得分:1)
来自MDN:
ECMAScript 2015中引入的JavaScript类主要是基于JavaScript现有的基于原型的继承的语法糖。类语法没有向JavaScript引入新的面向对象的继承模型。
您可以使用Babel REPL之类的工具来查看上面基于类的ES6代码如何转换为ES5,基于原型的代码:
class User {
constructor(name) {
this.name = name;
}
sayHi() {
alert(this.name);
}
}
let user = new User("John");
user.sayHi();
"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();
所有ES6 +功能都可以转换成ES5--它完全是有效的语法糖。 ES5中仍然可以实现所有“新功能”。我认为,这称为“一个JavaScript”原则。