如何继承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 {
...
}