function a () {
return "foo";
}
a.b = function () {
return "bar";
}
function c () { };
c.prototype = a;
var d = new c();
d.b(); // returns "bar"
d(); // throws exception, d is not a function
d
是否有某种方法可以成为一个函数,但仍然继承a
的属性?
答案 0 :(得分:10)
实际上,事实证明这是可能的,尽管是以非标准的方式。
Mozilla,Webkit,Blink / V8,Rhino和ActionScript提供了非标准的 __proto__
属性,允许在创建对象后更改对象的原型。在这些平台上,可以使用以下代码:
function a () {
return "foo";
}
a.b = function () {
return "bar";
}
function c () {
return "hatstand";
}
c.__proto__ = a;
c(); // returns "hatstand"
c.b(); // returns "bar"; inherited from a
这可能对任何不需要担心跨平台兼容性的人都有用。
但请注意,只能继承对象的属性。例如:
var d = {};
d.__proto__ = a;
d.b(); // returns "bar"
d(); // throws exception -- the fact that d is inheriting from a function
// doesn't make d itself a function.
答案 1 :(得分:8)
简短回答:不可能。
这段代码:
var d = new c();
自动假定d
是一个对象。除非c
是内置对象的构造函数,例如Function
。但是如果语言已经定义了c
,你就无法操纵它的原型,也不能从你喜欢的任何东西“继承”它。好吧,在一些口译员中你可以,但是你无法安全地在所有口译员中做到 - 标准说:“你不会弄乱标准物品,或者翻译会打击你!”。
内置对象是“唯一的”,JavaScript不提供复制它们的方法。如果不采用不兼容的技巧,就无法重新创建字符串,数字,函数等。
答案 2 :(得分:3)
是的,如果您使用Daniel Cassidy提到的__proto__
属性,则可以使用。诀窍是让c
实际返回一个已将a
附加到其原型链的函数。
function a () {
return "foo";
}
a.b = function () {
return "bar";
}
function c () {
var func = function() {
return "I am a function";
};
func.__proto__ = a;
return func;
}
c.prototype = a;
var d = new c();
d.b(); // returns "bar"
d(); // returns "I am a function"
但是,如果您希望instanceof
返回更好的结果,则需要对原型链进行一些调整。
d instanceof c // true
d instanceof a // false
c instanceof a // false
答案 3 :(得分:3)
基于discussion on meta about a similar question我在此基于@alexander-mills原始
发布此答案首先创建一个继承Function
const obj = Object.create(Function.prototype); // Ensures availability of call, apply ext
然后将自定义方法和属性添加到obj
接下来声明函数
const f = function(){
// Hello, World!
};
并将obj
设为f
Object.setPrototypeOf(f,obj);
const obj = Object.create(Function.prototype);
// Define an 'answer' method on 'obj'
obj.answer = function() {
// Call this object
this.call(); // Logs 'Hello, World'
console.log('The ultimate answer is 42');
}
const f = function() {
// Standard example
console.log('Hello, World');
};
Object.setPrototypeOf(f, obj);
// 'f' is now an object with an 'answer' method
f.answer();
// But is still a callable function
f();

答案 4 :(得分:1)
它是否必须真正成为原型链?您可以使用mixin模式使函数具有a的所有属性。如果你真的想要,你甚至可以用一个漂亮的“新”语法来包装它来伪造它。
function a () {
return "foo";
}
a.b = function () {
return "bar";
}
function c () {
var f = function(){
return a();
};
//mixin all properties on a
for(var prop in a){
f[prop] = a[prop];
}
return f; //just returns the function instead of "this"
};
var d = new c(); //doesn't need the new keyword, but just for fun it still works
alert(d()); //show "foo"
alert(d.b()); //shows "bar"
您可以在不影响a的情况下向d添加属性。这个和你想要的唯一区别是对a的改变不会影响c的现有“实例”。
答案 5 :(得分:-1)
这是我一直试图做的事情。特别感谢上述作者的意见。
这是使用“可调用对象”的链式实现:
var $omnifarious = (function(Schema){
var fn = function f(){
console.log('ran f!!!');
return f;
};
Schema.prototype = {
w: function(w){ console.log('w'); return this; },
x: function(x){ console.log('x'); return this; },
y: function(y){ console.log('y'); return this; }
};
fn.__proto__ = (new Schema()).__proto__;
return fn;
})(function schema(){ console.log('created new schema', this); });
console.log(
$omnifarious()().w().x().y()()()
);
此外,使用此“架构”方法,可以在interface
的{{1}} Object.freeze()
或Schema
上使用prototype
创建可重复使用的__proto__
宾语。这可能看起来像这样:fn.__proto__ = Object.freeze(new Schema().__proto__)
- 这不是一个实际的例子,可能需要更多。那就是说,它是一个不同的讨论。尝试一下,让我知道!
希望这有用。