Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/439.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaScript对象可以有一个原型链,但也可以是一个函数吗?_Javascript_Inheritance - Fatal编程技术网

JavaScript对象可以有一个原型链,但也可以是一个函数吗?

JavaScript对象可以有一个原型链,但也可以是一个函数吗?,javascript,inheritance,Javascript,Inheritance,有没有办法让d成为一个函数,但仍然从a继承属性?简短回答:不可能 这一行代码: 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是一

有没有办法让
d
成为一个函数,但仍然从
a
继承属性?

简短回答:不可能

这一行代码:

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
是一个对象。除非
c
是内置对象的构造函数,例如
函数
。但是,如果
c
已经由该语言定义,您就不能操纵它的原型,也不能从任何您喜欢的地方“继承”它。好吧,在一些口译员中你可以,但你不能在所有口译员中都安全地做到这一点——标准说:“你不能弄乱标准对象,否则口译员会揍你!”


内置对象是“唯一的”,JavaScript不提供复制它们的方法。如果不使用不兼容的技巧,就不可能重新创建字符串、数字、函数等等。

它实际上必须是一个原型链吗?可以使用mixin模式使函数具有函数的所有属性。如果你真的想要,你甚至可以用一个漂亮的“新”语法来伪装它

var d = new c();

可以在不影响a的情况下向d添加属性。这与您想要的唯一区别是,对a的更改不会影响c的现有“实例”。

事实上,这是可能的,尽管是以非标准的方式

Mozilla、Webkit、Blink/V8、Rhino和ActionScript提供了一个非标准的
\uuuuuuu proto\uuuuuuu属性,允许在对象创建后更改其原型。在这些平台上,可以使用以下代码:

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"
这可能对任何不需要担心跨平台兼容性的人都有用

但是,请注意,只能继承对象的属性。例如:

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

是的,如果您使用Daniel Cassidy提到的
\uuuu proto\uuuu
属性,这是可能的。诀窍是让
c
实际返回一个已将
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.
但是,如果希望
instanceof
返回更好的结果,则需要对原型链进行更多调整

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"

这是我一段时间以来一直在努力做的事情。特别感谢以上作者的投入

下面是使用“可调用对象”的链式实现:

此外,通过这种“模式”方法,可以使用
Object.freeze()
Schema
原型
原型
对象上创建一个可重用的
接口
。这可能是这样的:
fn.\uuuuu proto\uuuu=Object.freeze(新模式()。\uuuuu proto\uuuu)
——这不是一个实际的示例,可能需要更多。也就是说,这是一个不同的讨论。试试看,让我知道

希望这对你有帮助。

基于a,我在这里根据原文发布这个答案


现在可以以符合标准的方式完成此操作 首先创建一个继承
函数的对象

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()()()
);
然后将自定义方法和属性添加到
obj

接下来声明函数

const obj = Object.create(Function.prototype);  // Ensures availability of call, apply ext
并将
obj
设置为
f

const f = function(){
    // Hello, World!
};
演示
const obj=Object.create(Function.prototype);
//在“obj”上定义“应答”方法
obj.answer=函数(){
//称这个对象为
this.call();//记录“你好,世界”
log(“最终答案是42”);
}
常数f=函数(){
//标准示例
log('Hello,World');
};
setPrototypeOf(f,obj);
//“f”现在是具有“answer”方法的对象
f、 答案();
//但仍然是一个可调用函数

f()是的,我求助于使用mixin。在我的例子中,a被修改的可能性很小,修改应该反映在d中,但在实践中这不太可能是一件大事。投票否决。这是可能的!AngularJS有一个名为
$http
的模块。用法可以是:
$http({})
$http.post()
。这是可能的,但如何实现?@Cody
函数$http(){/*code*/}$http.post=function()!我将纠正投票。很抱歉。顺便说一句,我想我有一个解决办法——如果有兴趣的话,请看我的编辑。这在一个相当标准的方式下成为可能,请看
const f = function(){
    // Hello, World!
};
Object.setPrototypeOf(f,obj);