【问题标题】:Javascript constructors with parameters带参数的 Javascript 构造函数
【发布时间】:2012-09-30 11:40:30
【问题描述】:

在尝试了解 javascript 构造函数时,我一直在查看 this question。

在我看来,我理解它是合理的,但具有讽刺意味的是,当我尝试运行类似的代码时,它根本不适合我。

这是我的代码

function Car(name) {
    this.Name = name;
    this.Year = 1999;
}

Car.prototype.Drive = function() {
    document.write("My name is '" + this.Name + "' and my year is '" + this.Year + "'. <br />");
};

SuperCar = function () { };
SuperCar.prototype = new Car();

function SuperCar(name) {
    Car.call(this, name);
}

var MyCar = new Car("mycar");
var MySuperCar = new SuperCar("my super car");

MyCar.Drive();
MySuperCar.Drive();

首先是这一行

SuperCar = function () { };

是它运行所必需的。如果我忽略它,我会在这一行出现错误“SuperCar 未定义”。

SuperCar.prototype = new Car();

我真的不明白为什么有必要将 SuperCar 声明为空函数。

其次,当我运行代码时,我会得到这个结果

My name is 'mycar' and my year is '1999'. 
My name is 'undefined' and my year is '1999'. 

显然,对于 MySuperCar,SuperCar(name) 函数从未被调用,但 Car() 被调用。

添加这一行没有帮助

SuperCar.prototype.constructor = SuperCar;

这个也没有

SuperCar.prototype.constructor = function(name) {
    Car.call(this, name);
};

(我一直在 IE 9 和 Chrome 22 上的脚本标签内运行代码)

我应该如何正确定义采用名称参数的 SuperCar 构造函数?或者,换一种说法,我怎样才能让新的 SuperCar("my super car") 调用按我预期的方式运行(将名称设置为“my super car”)?

【问题讨论】:

  • Fiddle: jsfiddle.net/userdude/Gs4qu 一般来说,你可能会远离document.write,我建议改为document.body.innerHTML = "blah blah blah&lt;br&gt;";,或者DOM方法。
  • 如果我注释掉您要询问的函数变量,它也可以工作:jsfiddle.net/userdude/Gs4qu/1 正下方,您已经声明了 function SuperCar(name){...},并且提升将其置于范围的顶部。因此,除非有一段时间该函数不存在或者最初是一个变量函数或函数变量(谁能分辨出区别?),否则我不明白为什么会出现问题。我在这里也谈论 Chrome。

标签: javascript inheritance constructor prototypal-inheritance


【解决方案1】:

您不应该真正创建Car 的实例作为原型,而只创建一个继承自Car.prototype 的对象。详情请见What is the reason to use the 'new' keyword at Derived.prototype = new Base。相反,使用

SuperCar.prototype = Object.create(Car.prototype);

您的问题是您的 SuperCars 是由空函数创建的 - 它返回一个没有任何属性的对象。然而,它们继承自new Car(),其name 是undefined。这发生在您的小提琴中,因为 函数声明(以 function 关键字开头,查看 this explanation)被提升(在范围内随处可用)并被行覆盖

SuperCar = function () { };

这样您的SuperCar 构造函数就不会再调用Car 构造函数了。 Fixed fiddle

【讨论】:

    【解决方案2】:

    您不需要空函数。您创建了一个空的SuperCar 函数,然后设置了它的原型,然后用SuperCar 的新 定义重写了它。

    function SuperCar() {}
    SuperCar.prototype = new Car();
    
    function SuperCar() {} // original SuperCar overwritten
    

    【讨论】:

    • 不,您不需要将constructor 属性设置为新实例。
    • 不,第二个函数声明也不会覆盖第一个。
    • @Bergi 但绝对是那个空函数做到了,因为当我把它拿出来时它工作正常。
    • 是的,但它是原始函数声明上方的函数 表达式 - 请参阅我的答案
    猜你喜欢
    • 2016-08-06
    • 2018-03-31
    • 2011-10-08
    • 2017-06-12
    • 2019-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多