Javascript:来自[用户定义的原型]的变量不可用

时间:2011-08-12 05:38:13

标签: javascript prototype-programming inheritance

我使用面向Web开发人员的专业JavaScript 这本书播放javascript。我在第6.2.6节中练习了一个例子。代码如下:

function creatPrototype(subType, superType) 
{
    function subTypePrototype(){};
    subTypePrototype.prototype = superType.prototype;
    subTypePrototype.constructor = subType;
    subTypePrototype.str = "say";
    return new subTypePrototype();
}

function Person(name, age) 
{
    this.name = name;
    this.age = age;
}
Person.prototype.say = function(){
    writeln("bill say");
}


function itMan(name, age){
    Person.apply(this, arguments); 
}
itMan.prototype = creatPrototype(itMan, Person); 


var Bill = new itMan("bill", 25);

writeln(itMan.prototype.str);    //expect "say"
writeln(Person.prototype == itMan.prototype.prototype);   //expect true
Bill.say();  //expect "bill say"

结果是:

  

未定义

     

     

比尔说

为什么吗

  1. itMan.prototype.str假设“说”

  2. Person.prototype AND itMan.prototype.prototype应指向同一个对象

  3. Bill.say()正确运行,因此原型链正常。

3 个答案:

答案 0 :(得分:2)

您必须考虑哪个属性属于构造函数,哪个属于实例prototype是函数的属性,但constructorstr应该都是实例的属性。

这应该这样做:

function createPrototype(subType, superType) 
{
    function subTypePrototype(){};
    subTypePrototype.prototype = superType.prototype;

    var newPrototype = new subTypePrototype();

    newPrototype.constructor = subType;
    newPrototype.str = "say";
    return newPrototype;
}

但是,因为你也是passong subType,你实际上可以直接分配原型:

function inherit(subType, superType) 
{
    function tconstr(){};
    tconstr.prototype = superType.prototype;

    subType.prototype = new tconstr();

    subType.prototype.constructor = subType;
    subType.prototype.str = "say";
}

然后只需用

调用它
inherits(itMan, Person);

  

Person.prototype和itMan.prototype.prototype应该指向同一个对象

请记住,prototype功能的属性,而不是对象的属性。但是itMan.prototype是一个对象。除非明确引用它,否则无法访问对象原型(但我不会这样做)。

使用ECMAScript 5,有一种方法可以使用Object.getPrototypeOf [MDN]来获取原型。这仅适用于较新的浏览器。

以下是您的代码working example

答案 1 :(得分:1)

代码有些错误,试试这段代码

function creatPrototype(subType, superType) 
{
    function subTypePrototype(){
    this.prototype = superType.prototype;
    this.constructor = subType;
    this.str = "say";
}


    return new subTypePrototype();
}

function Person(name, age) 
{
    this.name = name;
    this.age = age;
}
Person.prototype.say = function(){
    document.writeln("bill say");
}


function itMan(name, age){
    Person.apply(this, arguments); 
}
itMan.prototype = creatPrototype(itMan, Person); 


var Bill = new itMan("bill", 25);

document.writeln(itMan.prototype.str);    //expect "say"

document.writeln(Person.prototype == itMan.prototype.prototype);   //expect true
Bill.prototype.say();  //expect "bill say"

在您的代码中,您没有使用this对象,因此itMAn没有变量str, 你在用 subTypePrototype.constructor = subType;subTypePrototype.prototype = superType.prototype; 因此Bill.say正在运作,Person.prototype == itMan.prototype.prototype无效。

答案 2 :(得分:0)

Prototype是一个保留关键字,使用它时必须非常小心 Articles on prototype keyword

您的代码中存在多个问题。

然后在你的createSubPrototype中:

return new subTypePrototype();

您正在创建一个函数,然后您将返回已执行的函数结果,您应该返回指向函数的指针,如

return subTypePrototype;

但你不应该创建一个函数,因为它似乎想要检索父“prototype”:)

所以你的代码确实应该更像:

function createPrototype(subType, superType) 
{
  subTypePrototype = superType.prototype;
  subTypePrototype.constructor = subType; //- beware this is wrong !!!
  subTypePrototype.str = "say";
  return subTypePrototype;
}

检查我标记为错误的行,这样做是为了更新sub&父类型

怎么做: 话虽如此,如果你想扩展一个对象,我会建议你使用现有的libs。 (jQuery,Mootools等)。 Here a sample on how to do it properly