将下面的代码使用function实现一遍:
class Person {
constructor(name) {
this.name = name;
}
getName() {
console.log(this.name);
}
}
使用function可以有简单的如下实现:
function myPerson(name) {
this.name = name;
}
myPerson.prototype.getName = function () {
console.log(this.name);
};
接下来可以考虑一下,class的特性,为其实现添砖加瓦
- class是ES6的特性,是在严格模式下执行的,在行首加入如下内容:
`use strict`;
function可以直接调用,但class不可以直接调用,只能使用new来进行调用,直接调用class看会出现什么结果:
Person("小李");
运行结果:
TypeError: Class constructor Person cannot be invoked without 'new'
处理一下上面的问题,我们知道,class只能使用new调用,new的话会创建一个构造函数的实例,同时会改变this的指向,验证this的指向即可:
function myPerson(name) {
// 验证this指向
if (!(this instanceof myPerson)) {
throw new TypeError(
"Class constructor Person cannot be invoked without `new`"
);
}
this.name = name;
}
myPerson('小李')
class实例中的function是不可被枚举的,而function实例中的是可以的:
const p1 = new Person("class");
const p2 = new myPerson("function");
for (let key in p1) {
console.log("class:", key);
}
console.log("------------------------");
for (let key in p2) {
console.log("function:", key);
}
运行结果如下:
class: name
------------------------
function: name
function: getName
那么需要将myPerson原型上的挂载的方法设置成不可枚举:
Object.defineProperty(myPerson.prototype, "getName", {
value: function () {
console.log(this.name);
},
enumerable: false,
});
- 在JavaScript中只要是
function都可以使用new来调用,但class中定义的function不行:
new p1.getName();
执行结果:
new p1.getName();
^
TypeError: p1.getName is not a constructor
同样验证this指向即可,如果this在原型链上找不到的话,那么就是使用了一些奇怪的方式调用这个function
Object.defineProperty(myPerson.prototype, "getName", {
value: function () {
if (!(this instanceof myPerson)) {
throw new TypeError("getName is not a constructor");
}
console.log(this.name);
},
enumerable: false,
});
new p2.getName();
完整代码:
`use strict`;
function myPerson(name) {
// 验证this指向
if (!(this instanceof myPerson)) {
throw new TypeError(
"Class constructor Person cannot be invoked without `new`"
);
}
this.name = name;
}
Object.defineProperty(myPerson.prototype, "getName", {
value: function () {
if (!(this instanceof myPerson)) {
throw new TypeError("getName is not a constructor");
}
console.log(this.name);
},
enumerable: false,
});