首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何继承javascript函数?

如何继承javascript函数?
EN

Stack Overflow用户
提问于 2011-09-24 20:54:21
回答 2查看 11.1K关注 0票数 50
// 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"

.__proto__是非标准的,已弃用。

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

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

new Constructor返回一个对象,而不是一个函数。

动机:-一个跨浏览器的finherit

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;
};

我不相信这是可能的,所以我们可能应该提出一个Function.create到es讨论邮件列表

/*
  Creates a new function whose prototype is proto.
  The function body is the same as the function fbody.
  The hash of propertydescriptors props is passed to defineproperties just like
  Object.create does.
*/
Function.create = (function() {
  var functionBody = function _getFunctionBody(f) {
    return f.toString().replace(/.+\{/, "").replace(/\}$/, "");
  };
  var letters = "abcdefghijklmnopqrstuvwxyz".split("");

  return function _create(proto, fbody, props) {
    var parameters = letters.slice(0, fbody.length);
    parameters.push(functionBody(fbody));
    var f = Function.apply(this, parameters);
    f.__proto__ = proto;
    Object.defineProperties(f, props);
    return f;
  };
})();

Related es-discuss mail

正如在ES讨论线程中提到的,存在一个ES:strawman <|原型操作符,它可以实现这一点。

让我们看看使用<|会是什么样子

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
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-10-14 11:25:20

我希望我对此的理解是正确的。

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

从runtime.

  • (functorObj instanceof MyClass)的角度来说,这是非常昂贵的,true.

  • Properties是不能直接访问的(如果它们都是通过引用赋值的,那就另当别论了,但
  1. 是按值赋值的)。这可以通过defineProperty的访问器或简单命名的访问器方法来解决(这似乎就是您正在寻找的,如果您不需要跨引擎支持/向后compatability).
  2. You're,则只需通过getters/setters将所有属性添加到函数器,而不仅仅是函数,这可能会遇到最终的原生原型(如果您正在继承,则为Object.prototype或Array.prototype )可能无法运行的边缘情况,因为expected.
  3. Calling functorObj(someArg)将始终使this上下文成为对象。无论它是否被调用functorObj.call(someOtherObj, someArg) (这不是方法调用though)
  4. Because的情况),函数器对象是在请求时创建的,它将被及时锁定,并且操作初始原型不会像普通对象那样影响已分配的函数器对象(修改MyClass.prototype不会影响任何函数器对象,反之亦然)。

不过,如果你轻轻地使用它,这一切都不应该是什么大问题。

在您的类的原型中定义类似于...

// 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 aobj = new MyClass();
var afunctor = aobj.asFunctor();
aobj.someMethodOfMine(); // << works
afunctor.someMethodOfMine(); // << works exactly like the previous call (including the this context).
afunctor('hello'); // << works by calling aobj.execute('hello');

(aobj instanceof MyClass) // << true
(afunctor instanceof MyClass) // << false
(afunctor.asObject === aobj) // << true

// to bind with a previous function...
var afunctor = (new MyClass()).asFunctor(function() { alert('I am the original call'); });
afunctor() // << first calls the original, then execute();
// To simply wrap a previous function, don't define execute() in the prototype.

您甚至可以用链条绑定无数其他对象/函数/等等,直到牛回家为止。只要稍微重构一下代理调用即可。

希望这能有所帮助。当然,您还可以更改工厂流程,以便在不使用new操作符的情况下调用构造函数,然后实例化一个新对象并返回函数器对象。无论你喜欢什么(你当然也可以用其他方式来做)。

最后,要让任何函数以一种更优雅的方式成为函数器的执行运算符,只需将代理函数作为Function.prototype的方法,并将要包装的对象传递给它(当然,您必须将templateFunctionthis交换,将this与参数交换)……

var functor = (function() { /* something */ }).asFunctor(aobj);
票数 10
EN

Stack Overflow用户

发布于 2018-02-23 23:09:13

使用ES6可以从Function继承,请参阅(复制)问题

javascript class inherit from Function class

default export Attribute extends Function {
...
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7539148

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档