我有一个用Javascript编写的天气应用程序,它包含一个温度构造函数(以及其他函数)。在没有详细说明的情况下,我注意到一种非常奇怪的行为使我的应用程序崩溃。当我创建一个温度对象数组并向其添加一个对象时,然后在控制台中显示它,然后替换为一个新的温度对象(该对象具有相同的数据),然后再次在控制台中显示它,它以不同的方式显示它。这是我的密码:
let weatherData = [];
weatherData[0] = new Temperature(200);
console.log(weatherData[0]);
weatherData[0] = new Temperature(200);
console.log(weatherData[0]);这是控制台输出:
Temperature {
value: 200,
}
{
value: 200,
}因此,当我第一次将对象添加到数组时,我不能使用温度从另一个类继承的方法。这就是我的意思:
let weatherData = [];
weatherData[0] = new Temperature(200);
weatherData[0].inheritedMethod();/\抛出错误weatherData.inheritedMethod()不是函数
let weatherData = [];
weatherData[0] = new Temperature(200);
weatherData[0] = new Temperature(200);
weatherData[0].inheritedMethod();/\工作很好
有人能给我解释一下为什么会发生这种事吗?我该怎么解决?
温度等级:
//inherits from WeatherData
const WeatherData = require("./WeatherData");
module.exports = function Temperature(time, place, type, unit, value) {
WeatherData.call(this, time, place, type, unit, value);
Temperature.prototype = Object.create(WeatherData.prototype);
Temperature.prototype.convertToF = function () {
...
};
Temperature.prototype.convertToC = function () {
...
};
};发布于 2020-09-17 18:45:00
所有这些问题都是由于在构造函数中执行以下代码而引起的:
Temperature.prototype = Object.create(WeatherData.prototype);
Temperature.prototype.convertToF = function () {
...
};
Temperature.prototype.convertToC = function () {
...
};这应该放在构造函数之外,以便它立即执行,而且只执行一次。
控制台输出差
首先,控制台可以自由地以自己的方式显示对象。尽管如此,这两个对象仍然有很大的不同:第一个对象是在尚未将上述分配分配给Temperature.prototype时创建的,因此在执行new Temperature()时隐式创建的this对象仍然是从原始Temperature.prototype生成的。
但是,在创建第二个实例时,Temperature.prototype已经改变了,这直接影响了this的构造方式。它现在是以WeatherData.prototype为原型构建的。
请参阅此片段中的不同之处:
// Set up
function WeatherData(time, place, type, unit, value) {
if (time !== undefined) this.time = time;
}
WeatherData.prototype.inheritedMethod = function() {};
function Temperature(time, place, type, unit, value) {
WeatherData.call(this, time, place, type, unit, value);
// Wrongly positioned code:
Temperature.prototype = Object.create(WeatherData.prototype);
Temperature.prototype.convertToF = function () {};
Temperature.prototype.convertToC = function () {};
};
// test case:
console.log(Object.getPrototypeOf(new Temperature(200)).constructor.name); // Temperature
console.log(Object.getPrototypeOf(new Temperature(200)).constructor.name); // WeatherData
错误.inheritedMethod()不是一个函数
由于第一个实例是在原型对象仍然是原始Temperature.prototype时创建的,并且尚未设置来自WeatherData的继承,因此该实例没有来自WheatherData的继承,因此它的原型链中没有inheritedMethod。
在这里,我们检查原型链中的一个级别,并发现在第一个例子中,该级别是Object。只有在第二种情况下,我们才使用WeatherData作为构造函数:
// Set up
function WeatherData(time, place, type, unit, value) {
if (time !== undefined) this.time = time;
}
WeatherData.prototype.inheritedMethod = function() {};
function Temperature(time, place, type, unit, value) {
WeatherData.call(this, time, place, type, unit, value);
// Wrongly positioned code:
Temperature.prototype = Object.create(WeatherData.prototype);
Temperature.prototype.convertToF = function () {};
Temperature.prototype.convertToC = function () {};
};
// test case:
console.log(Object.getPrototypeOf(Object.getPrototypeOf(new Temperature(200))).constructor.name); // Object
console.log(Object.getPrototypeOf(Object.getPrototypeOf(new Temperature(200))).constructor.name); // WeatherData
长话短说
所有这些都是为了说明这些赋值不应该发生在构造函数中,而应该发生在构造函数之外。
使用更现代的class ... extends语法,情况要简单得多:
// Set up
class WeatherData{
constructor(time, place, type, unit, value) {
if (time !== undefined) this.time = time;
}
inheritedMethod() { console.log("inherited method called") }
}
class Temperature extends WeatherData {
constructor(time, place, type, unit, value) {
super(time, place, type, unit, value);
}
convertToF() {};
convertToC() {};
}
// test case:
new Temperature(200).inheritedMethod();
new Temperature(200).inheritedMethod();
https://stackoverflow.com/questions/63943738
复制相似问题