【问题标题】:Make a javascript function inherit a prototype [duplicate]使javascript函数继承原型[重复]
【发布时间】:2012-12-14 01:50:08
【问题描述】:

可能重复:
How do I make a callable JS object with an arbitrary prototype?

假设我们有多个单独的函数,我们可以在它们自己的上下文中单独调用它们;但它们也继承了一些其他对象的原型。像这样:

//Here is the parent object:
var Human = function(){
    this.isAlive = true;
};
Human.prototype.say = function(what){
    alert(what + '!');
};

//These will inherit from it:
var ninja = function() {
    alert("I'm a ninja!");
}
var samurai = function(){
    alert("I'm a samurai!");
}

//Now, how can I make ninja and samurai behave like this:
ninja(); //I'm a ninja!
samurai(); //I'm a samurai!
ninja.say('Hello'); //Hello!

//And they should keep their inheritance. Like:
Human.prototype.die = function(){
    this.isAlive = false;
}

ninja.die();
ninja.isAlive == false;

samurai.isAlive == true;

换句话说,有没有办法让两个对象继承另一个对象的原型,但仍然可以作为函数调用?

注意:我将在 Adob​​e ExtendScript(又名 Crippled Javascript)中使用它,它对现代 javascript 了解不多。就像, Object.defineProperty 在其中不起作用。那么,有没有一种正常、标准的方法来做到这一点?

【问题讨论】:

  • 如果不声明new ninja(),我认为您无法做到这一点,但也许有人可以证明我错了。
  • +1 很好的发现——我想说那个答案证明我错了
  • @apslillers 是的,我不认为这些是完全相同的问题。
  • 为了记录,我认为这在旧 js 中是不可行的。
  • 它是 100% 使用.prototype,还是只是在寻找它来继承静态方法/属性?答案取决于您在寻找什么以及为什么。

标签: javascript inheritance prototype


【解决方案1】:

使用 apsillers 的链接问题,我能够通过一次调整使其工作:Human 的属性和方法被定义为一个对象:

试试看:http://jsfiddle.net/lbstr/JZP2S/

关键是HumanMaker 函数。在基本层面上,它接受一个函数并向其添加Human 原型。这允许您调用您的函数,从Human 获取所有属性并吃掉它。这里是:

function HumanMaker(f) {
    var h = Human;
    h.__proto__ = f.__proto__;
    f.__proto__ = h;
    return f;
}

你可以这样调用它:

var ninja = HumanMaker(function() {
    alert("I'm a ninja!");
});

这是全部内容:

var Human = {
    isAlive: true,
    say: function(what){
        alert(what + '!');
    },
    die: function(){
        this.isAlive = false;
    }
};

function HumanMaker(f) {
    var h = Human;
    h.__proto__ = f.__proto__;
    f.__proto__ = h;
    return f;
}

//These will inherit from it:
var ninja = HumanMaker(function() {
    alert("I'm a ninja!");
});
var samurai = HumanMaker(function(){
    alert("I'm a samurai!");
});

//Now, how can I make ninja and samurai behave like this:
ninja(); //I'm a ninja!
samurai(); //I'm a samurai!
ninja.say('Hello'); //Hello!


ninja.die();
ninja.isAlive == false;

samurai.isAlive == true;​

【讨论】:

    【解决方案2】:

    我一直觉得函数式继承模式更容易理解:

    var human = function(){
        var me = {};
        var _isAlive = true;
        Object.defineProperty(me, "isAlive", {
            get: function() { return _isAlive}
        });
    
        me.say=function(what){
            if(_isAlive)
              alert(what+'!');  
            else
               throw new Error('I am dead!');                
        }
        me.die=function(){
          _isAlive = false;                
        }
        return me;
    };
    
    var person = function(){
        var me = human();
        return me;
    };        
    
    var ninja = function(){
        var me = human();
        me.say = function(what){
            if(me.isAlive)
              alert(what+', I am a ninja!');  
            else
               throw new Error('I am dead!');          
        };
        return me;
    };
    
    var myPerson = person();
    myPerson.say('hi');
    
    var myNinja = ninja();
    myNinja.say('hello');
    

    我在这里留下了一个演示:http://jsfiddle.net/vtortola/nbpPt/

    干杯。

    【讨论】:

    • 不错的代码,但除非我不理解您的代码,否则我认为它不能解决问题。忍者是不可调用的。而人类是不可扩展的。比如,如果 ninja 是 Human 的一个实例,Human 突然采用了一个新的原型方法,那么 ninja 应该也有那个方法,但仍然可以作为普通函数调用。
    猜你喜欢
    • 2019-01-24
    • 2016-07-04
    • 2020-12-28
    • 2021-11-14
    • 1970-01-01
    • 2014-05-08
    • 2016-11-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多