Javascript-经理是一个人,但不是经理本身?功能/原型继承

Javascript - Manager is a Person but not a Manager itself? Functional/Prototypal Inheritance

本文关键字:功能 继承 原型 一个人 Javascript-      更新时间:2023-09-26

我试图用函数/原型继承来编码继承,我创建了两个构造函数Person和Manager。一切听起来都很好,但manager本身并不是manager对象。相反,它是一个Object对象。如何解决此问题?

 // <![CDATA[
         var Person = function(name, age)
         {
            this.name = name;
            this.age = age;
            this.desc = function()
            {
               return "my name is " + this.name + " I'm " + this.age; 
            }
         }
         var Manager = function(name, age, dept)
         {
            var manager = new Person(name, age);
            manager.dept = dept; 
            manager.mgrDesc = function()
            {
               return manager.desc() + " and I work at the " + manager.dept + " department";
            }
            return manager;
         }
         Manager.prototype = new Person();
         var manager = new Manager("Foo", 3, "IT");
         console.log(manager.mgrDesc());
         console.log(manager instanceof Person);
         console.log(manager instanceof Manager);
       // ]]>

继承的方式打破了Manager函数和从中返回的对象之间的任何关系

var manager = new Person(name, age);

然后从CCD_ 3函数中返回。当您从构造函数返回一个对象时,它将替代new运算符为您创建的对象。

下面是一个在JavaScript中进行这种继承的例子,同时保持该结构的完整性:

var Thing = (function() {
    var p;
    function Thing(name) {
        this.name = name;
    }
    p = Thing.prototype;
    p.one = one;
    function one() {
        console.log("Thing#one: name = " + this.name);
    }
    p.two = two;
    function two() {
        console.log("Thing#two: name = " + this.name);
    }
    p.three = three;
    function three() {
        console.log("Thing#three: name = " + this.name);
    }
    return Thing;
})();
var NiftyThing = (function(parent) {
    var proxy, p, pp;
    function NiftyThing(name) {
        parent.call(this, name);
    }
    proxy = function() { };
    proxy.prototype = parent.prototype;
    p = new proxy();
    // On ECMAScript5 systems, the three lines above could be
    // replaced with p = Object.create(parent.prototype);
    p.constructor = NiftyThing;
    NiftyThing.prototype = p;
    pp = parent.prototype;
    p.one = one;
    function one() {
        // Call parent
        pp.one.call(this);
        // And also do our own thing
        console.log("NiftyThing#one: name = " + this.name);
    }
    p.two = two;
    function two() {
        // Just do our own thing without calling parent
        console.log("NiftyThing#two: name = " + this.name);
    }
    // We don't override `three`
    return NiftyThing;
})(Thing);

当然,与其每次都在NiftyThing中写出所有这些内容,不如拥有一个可以重用的辅助脚本。我写了一个名为Lineage的文件,事实上,上面是一个文档页面的一部分,比较了在没有Lineage的情况下和使用CCD_7(当然,这是"没有"位)。即使您不使用Lineage,该页面也可能有助于理解JavaScript中类结构的管道是如何完成的。

必须注意的是:使用JavaScript的原型继承完全可以构建类结构(见上文),但请注意,JavaScript的原型遗传让您可以更灵活地完成任务。这是我喜欢JS的一点:在适当的时候,我可以做类的事情;当我只需要临时"使此对象从另一个对象派生"时,我也可以这样做(使用Object.create,其基本形式可以在ECMAScript5之前的引擎上填充)。


值得注意的是,你的问题中的代码有一个问题:

你通常会在上面的代码中看到这种反模式:

Manager.prototype = new Person();

Person的设计目的是构造实例,而不是原型。例如,考虑一下Person是否接受了name参数—在创建Manager.prototype对象时,您会将其命名为什么?

这就是为什么上面的代码没有做到这一点,而是做到了这一点(以PersonManager为例):

var proxy = function() { };
proxy.prototype = Person.prototype;
Manager.prototype = new proxy();
Manager.prototype.constructor = Manager;

请注意,我们创建了一个新对象,该对象使用Person.prototype作为其底层原型,但没有调用new Person(),因此我们不存在如果Person需要参数该怎么办的问题。

稍后,当初始化实例时,我们执行以下等效操作:

function Manager() {
    // Init super
    Person.call(this);
    // Do Manager stuff...
}

因为在这一点上,如果Person需要参数,我们就会有它们(要么是因为我们提供了硬编码版本,要么是因为Person0接受参数)。

使用return manager并不是在使用正在构建的this对象。相反,试试这个(未经测试):

var Manager = function(name, age, dept) {
    Person.call(this, name, age);
    this.dept = dept; 
    this.mgrDesc = function() {
       return this.desc() + " and I work at the " + this.dept + " department";
    }
}
var Manager, Person, manager,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };
Person = (function() {
  Person.name = 'Person';
function Person(name, age) {
  this.name = name;
  this.age = age;
}
Person.prototype.desc = function() {
  return "my name is " + this.name + " I'm " + this.age;
};
return Person;
})();
Manager = (function(_super) {
__extends(Manager, _super);
Manager.name = 'Manager';
function Manager(name, age, dept) {  
this.name = name
this.age = age
this.dept = dept
Manager.__super__.constructor.apply(this, arguments);
}
Manager.prototype.mgrDesc = function() {
  return this.desc() + " and I work at the " + this.dept + " department";
};
return Manager;
})(Person);
manager = new Manager("Foo", 3, "IT");
console.log(manager.mgrDesc());
console.log(manager instanceof Person);
console.log(manager instanceof Manager);

=>我叫Foo,今年3岁,在 IT部门工作

真实

真实