ES6
之前,js
的类都是由函数来实现的,那如果我想把 class
转为 function
, 需要注意什么呢?
# 开始转换
语法糖,本质上还是个构造函数,我们先实现一个基本的function
版本
类👇
class Example {
construcor(name) {
this.name = name;
}
getName() {
console.log(this.name);
}
}
函数👇
function Example(name) {
this.name = name;
}
Example.prototype.getName = function () {
console.log(this.name);
};
# 注意的点
类是严格模式的,所以要在构造函数上面加上"use strict"
;
"use strict"
function Example(name) {
this.name = name;
}
/*
...
*/
类只能通过new 来调用,不能直接来调用,所以我们是不能直接执行 Example()
的,执行会报错
怎么来实现呢? —— 通过验证 this
的指向,通过new
调用的 this
是类的实例,而直接调用的 this
则是 window
("use strict");
function Example(name) {
if (!(this instanceof Example)) {
throw new TypeError(
" Class constructor Example cannot be invoked without 'new'"
);
}
this.name = name;
}
类通过函数简写形式写的函数方法是添加到对象原型上的,所以现在我们也是往Example的原型上添加方法,但是这里要注意的是,这个方法是不可被枚举的,也就是说,打印实例对象上的属性,是访问不到这个方法的
怎么实现呢? —— 通过 Object.defineProperty()
来设置 enumerable: false
即可 👇
// 可枚举
Example.prototype.getName = function () {
console.log(this.name);
};
// 不可枚举
Object.defineProperty(Example.prototype, "getName", {
value: function () {
console.log(this.name);
},
enumerable: false,
});
最后一个区别比较的隐蔽,还是函数的属性方法,类的属性方法只能通过类的实例对象来调用👇
let e = new Example("test");
e.getName();
// test
如果你使用 new e.getName()
, 则会报错,JS
里默认所有的函数都是可以通过 new
来调用的,但是这里是个例外
怎么实现? —— 跟上面一样,通过判断 this
的指向即可
Object.defineProperty(Example.prototype, "getName", {
value: function () {
if (!(this instanceof Example)) {
throw new TypeError("e.getName is not a constructor");
}
console.log(this.name);
},
enumerable: false,
});
# 最终版本
class
转为 function
的效果就是下面这些代码了👇
("use strict");
function Example(name) {
if (!(this instanceof Example)) {
throw new TypeError(
" Class constructor Example cannot be invoked without 'new'"
);
}
this.name = name;
}
Object.defineProperty(Example.prototype, "getName", {
value: function () {
if (!(this instanceof Example)) {
throw new TypeError("e.getName is not a constructor");
}
console.log(this.name);
},
enumerable: false,
});