如何继承 javascript 函数?
// 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;
};
我不相信这是可能的,所以我们可能应该向 es 提出一个 Function.create
-讨论邮件列表
/*
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;
};
})();
正如 es-discuss 线程中提到的,存在一个 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
// 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__
is non-standard and deprecated.
How am I supposed to inherit prototypically creating an object but having that object be a function.
Object.create
returns an Object not a Function.
new Constructor
returns an Object not a Function.
Motivation: - A cross-browser 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;
};
I don't believe this is possible, so we should probably propose a Function.create
to the es-discuss mailing list
/*
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;
};
})();
As mentioned in the es-discuss thread there exists a ES:strawman <|
prototype operator which would allow for this.
Let's see what it would look like using <|
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我希望我能正确理解这一点。
我相信您想要一个既是预定义原型的实例(是的,一个类,只是不是经典类)又可以直接调用的函子?正确的?如果是这样,那么这就很有意义,并且非常强大和灵活(特别是在像 JavaScript 这样的高度异步环境中)。 遗憾的是,如果不操作
__proto__
,就无法在 JavaScript 中优雅地完成此操作。您可以通过分解一个匿名函数并复制对所有方法的所有引用(这似乎是您前进的方向)来充当代理类来完成此操作。这样做的缺点是......(functorObj instanceof MyClass)
永远不会是true
。defineProperty
使用访问器来解决,或者在必要时简单地命名访问器方法(这似乎就是您正在寻找的,只需使用defineProperty
将所有属性添加到仿函数中即可> 如果您不需要跨引擎支持/向后兼容性,则通过 getter/setter 而不仅仅是函数)。functorObj(someArg)
将始终使this
上下文成为对象,无论它是否被调用functorObj.call(someOtherObj, someArg)
(不过方法调用的情况并非如此)如果你轻轻地使用它,这一切都应该不是什么大问题。
在类的原型中定义类似的东西...
最终的用法看起来像...
您甚至可以链接绑定无数其他对象/函数/等,直到奶牛回家。只需稍微重构一下代理调用即可。
希望有帮助。哦,当然,您可以更改工厂流程,以便在不使用 new 运算符的情况下调用构造函数,然后实例化一个新对象并返回函子对象。不管你喜欢什么(你当然也可以用其他方式来做)。
最后,要让任何函数以更优雅的方式成为函子的执行运算符,只需将代理函数设为
Function.prototype
的方法,然后将其传递给要包装的对象(如果需要)做类似的事情(当然,您必须将templateFunction
与this
交换,并将this
与参数交换)...I hope that I'm understanding this right.
I believe you want a functor that's both an instance of a predefined prototype (yes, a class, just not a classic class) as well as directly callable? Right? If so, then this makes perfect sense and is very powerful and flexible (especially in a highly asynchronous environment like JavaScript). Sadly there is no way to do it elegantly in JavaScript without manipulating
__proto__
. You can do it by factoring out an anonymous function and copying all of the references to all of the methods (which seems to be the direction you were heading) to act as a proxy class. The downsides to this are...(functorObj instanceof MyClass)
will never betrue
.defineProperty
or simply named accessor methods if necessary (it appears that that is what you're looking for, just add all properties to the functor withdefineProperty
via getters/setters instead of just functions if you don't need cross-engine support/backwards compatability).functorObj(someArg)
will always make thethis
context be the object, regardless of if it's calledfunctorObj.call(someOtherObj, someArg)
(this is not the case for method calls though)If you use it gently though, none of this should be a big deal.
In your prototype of your class define something like...
Resulting usage would look something like...
You could even chain bind countless other objects/functions/etc until the cows came home. Just refactor the proxy call a bit.
Hope that helps. Oh, and of course you could change the factory flow so that a constructor called without the
new
operator then instantiates a new object and returns the functor object. However you prefer (you could surely do it other ways too).Finally, to have any function become the execution operator for a functor in a bit more elegant of a manner, just make the proxy function a method of
Function.prototype
and pass it the object to wrap if you want to do something like (you would have to swaptemplateFunction
withthis
andthis
with the argument of course)...使用 ES6 可以从
Function
继承,请参阅(重复)问题javascript类继承自Function类
With ES6 it's possible to inherit from
Function
, see (duplicate) questionjavascript class inherit from Function class