如何继承javascript函数?

如何继承javascript函数?,javascript,oop,function,inheritance,prototypal-inheritance,Javascript,Oop,Function,Inheritance,Prototypal Inheritance,是非标准的,不推荐使用 我应该如何继承原型来创建一个对象,但让该对象成为一个函数 Object.create返回一个对象而不是函数 new构造函数返回的是对象而不是函数 动机:-跨浏览器finherit // Don't break the function prototype. // pd - https://github.com/Raynos/pd var proto = Object.create(Function.prototype, pd({ "prop": 42 })); va

是非标准的,不推荐使用

我应该如何继承原型来创建一个对象,但让该对象成为一个函数

Object.create
返回一个对象而不是函数

new构造函数
返回的是对象而不是函数

动机:-跨浏览器
finherit

// Don't break the function prototype.
// pd - https://github.com/Raynos/pd
var proto = Object.create(Function.prototype, pd({
  "prop": 42
}));

var f = function() { return "is a function"; };
f.__proto__ = proto;

console.log(f.hasOwnProperty("prop")); // false
console.log(f.prop); // 42
console.log(f()); // "is a function"
我认为这是不可能的,所以我们可能应该建议一个
函数。为邮件列表创建

var finherit = function (parent, child) {
    var f = function() { 
        parent.apply(this, arguments);
        child.apply(this, arguments);
    };
    f.__proto__ = parent;
    Object.keys(child).forEach(function _copy(key) {
        f[key] = child[key];
    });
    return f;
};

正如在es讨论线程中提到的,存在一个es:strawman原型操作符,它允许这样做


让我们看看使用
会是什么样子,我希望我正确理解这一点

我相信你想要一个函子,它既是预定义原型的实例(是的,是一个类,只是不是一个经典类),又是可直接调用的?对吗?如果是这样的话,那么这就非常有意义,而且非常强大和灵活(特别是在像JavaScript这样的高度异步环境中)遗憾的是,如果不操纵
\uuuu proto\uuuu
,就无法在JavaScript中优雅地完成这项工作。您可以通过分解出一个匿名函数并将所有引用复制到所有方法(这似乎是您的方向)来充当代理类来实现这一点。这样做的缺点是

  • 这在运行时方面非常昂贵
  • (MyClass的functorObj实例)
    永远不会是
    真的
  • 属性将无法直接访问(如果它们都是通过引用指定的,这将是一个不同的故事,但基本体是通过值指定的)。这可以通过
    defineProperty
    访问器解决,或者如果需要,可以使用简单命名的访问器方法解决(看起来这就是您要寻找的,如果不需要跨引擎支持/向后兼容,只需使用
    defineProperty
    通过getter/setters将所有属性添加到函子中即可)
  • 您可能会遇到最终本机原型(如Object.prototype或Array.prototype[如果您继承该原型])可能无法按预期运行的边缘情况
  • 调用
    functorObj(someArg)
    将始终使
    this
    上下文成为对象,而不管它是否被调用
    functorObj.call(someOtherObj,someArg)
    (但对于方法调用,情况并非如此)
  • 由于函子对象是在请求时创建的,因此它将在时间上被锁定,并且操纵初始原型不会像影响普通对象那样影响分配的函子对象(修改MyClass.prototype不会影响任何函子对象,反之亦然)
  • 如果你轻轻地使用它,这一切都不会有什么大不了的

    在类的原型中定义如下内容

    var f1 = function () {
      console.log("do things");
    };
    
    f1.method = function() { return 42; };
    
    var f2 = f1 <| function () {
      super();
      console.log("do more things");
    }
    console.log(f1.isPrototypeOf(f2)); // true
    console.log(f2()); // do things do more things
    console.log(f2.hasOwnProperty("method")); // false
    console.log(f2.method()); // 42
    
    // This is you're emulated "overloaded" call() operator.
    MyClass.prototype.execute = function() {
       alert('I have been called like a function but have (semi-)proper access to this!');
    };
    
    MyClass.prototype.asFunctor = function(/* templateFunction */) {
       if ((typeof arguments[0] !== 'function') && (typeof this.execute !== 'function'))
          throw new TypeError('You really should define the calling operator for a functor shouldn\'t you?');
       // This is both the resulting functor proxy object as well as the proxy call function
       var res = function() {
          var ret;
          if (res.templateFunction !== null)
             // the this context here could be res.asObject, or res, or whatever your goal is here
             ret = res.templateFunction.call(this, arguments);
          if (typeof res.asObject.execute === 'function')
             ret = res.asObject.execute.apply(res.asObject, arguments);
          return ret;
       };
       res.asObject = this;
       res.templateFunction = (typeof arguments[0] === 'function') ? arguments[0] : null;
       for (var k in this) {
          if (typeof this[k] === 'function') {
             res[k] = (function(reference) {
                var m = function() {
                   return m.proxyReference.apply((this === res) ? res.asObject : this, arguments);
                };
                m.proxyReference = reference;
                return m;
             })(this.asObject[k]);
          }
       }
       return res;
    };
    
    由此产生的用法看起来像

    var f1 = function () {
      console.log("do things");
    };
    
    f1.method = function() { return 42; };
    
    var f2 = f1 <| function () {
      super();
      console.log("do more things");
    }
    console.log(f1.isPrototypeOf(f2)); // true
    console.log(f2()); // do things do more things
    console.log(f2.hasOwnProperty("method")); // false
    console.log(f2.method()); // 42
    
    // This is you're emulated "overloaded" call() operator.
    MyClass.prototype.execute = function() {
       alert('I have been called like a function but have (semi-)proper access to this!');
    };
    
    MyClass.prototype.asFunctor = function(/* templateFunction */) {
       if ((typeof arguments[0] !== 'function') && (typeof this.execute !== 'function'))
          throw new TypeError('You really should define the calling operator for a functor shouldn\'t you?');
       // This is both the resulting functor proxy object as well as the proxy call function
       var res = function() {
          var ret;
          if (res.templateFunction !== null)
             // the this context here could be res.asObject, or res, or whatever your goal is here
             ret = res.templateFunction.call(this, arguments);
          if (typeof res.asObject.execute === 'function')
             ret = res.asObject.execute.apply(res.asObject, arguments);
          return ret;
       };
       res.asObject = this;
       res.templateFunction = (typeof arguments[0] === 'function') ? arguments[0] : null;
       for (var k in this) {
          if (typeof this[k] === 'function') {
             res[k] = (function(reference) {
                var m = function() {
                   return m.proxyReference.apply((this === res) ? res.asObject : this, arguments);
                };
                m.proxyReference = reference;
                return m;
             })(this.asObject[k]);
          }
       }
       return res;
    };
    

    使用ES6,可以从
    函数继承
    ,请参见(重复)问题


    @patrick_-dw没有真正的帮助,但谢谢你;)@把你的名字改回来,帕特里克,你是个白痴。o/请告诉我,你现在还没有弄明白!哦,太好了。不久前,我在阅读关于对象文字语法的扩展时看到了operator的原型,但没有密切关注。ES5很不错,但是现在有很多很酷的东西被提出了,我只是希望他们能在不让我们等太久的情况下把它做好。酷。我从没听说过函子。我肯定会给我的下一个狗函子命名。这真的是一个伪函子(是的,有趣的名字)代理一切。这是一种草率的实现方式。有些语言本机支持这一点。如果EMCAScript5允许
    \uuuuu proto\uuuuu
    操作(或等效的替代标准)或运算符重载,JavaScript也会允许。遗憾的是,事实并非如此。尽管它的力量和灵活性。。。叹气。@stobbe先生,你能尝试一下用ES6代理来代替吗?(在chrome&FF中工作)。或者你可以欺骗并假装
    @Raynos-是的。事实上,这其中有相当一部分是为了支持ES5功能而编写的,但我故意避免使用它们,以展示如何以完全向后兼容的方式完成这项工作(所有当前和最近过时的引擎都可能支持这项工作)。这只是为了证明这是可以做到的。这里的问题令人沮丧的是,ES规范之间的差距是什么,所以我想提供一个在任何地方都适用的解决方案。@mr.stobbe主要的沮丧是ES5不能做到这一点,
    。\uuuuu protot\uuuu
    是一种非标准的不推荐的黑客,不属于ES的一部分。使用ES5功能无法做到这一点
    var functor = (function() { /* something */ }).asFunctor(aobj);
    
    default export Attribute extends Function {
    ...
    }