Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/411.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 使用调用super的方法分配浅克隆对象时出现TypeError_Javascript_Ecmascript 6 - Fatal编程技术网

Javascript 使用调用super的方法分配浅克隆对象时出现TypeError

Javascript 使用调用super的方法分配浅克隆对象时出现TypeError,javascript,ecmascript-6,Javascript,Ecmascript 6,我正在ChromeCanary63和Chrome61上测试以下代码。代码的目标是设置一个方法,该方法对类实例(z)调用super。在我的代码库中,有时属性块在添加到实例之前会使用Object.assign进行克隆,每当发生这种情况时,代码都会失败 我用下面的代码示例再现了这个问题。如果避免浅克隆(props=Object.assign({},props);),代码工作正常,但如果添加该行,则会得到TypeError:(中间值).bar不是函数 我尝试过使用Object.create(这个,Obj

我正在ChromeCanary63和Chrome61上测试以下代码。代码的目标是设置一个方法,该方法对类实例(
z
)调用super。在我的代码库中,有时属性块在添加到实例之前会使用Object.assign进行克隆,每当发生这种情况时,代码都会失败

我用下面的代码示例再现了这个问题。如果避免浅克隆(
props=Object.assign({},props);
),代码工作正常,但如果添加该行,则会得到
TypeError:(中间值).bar不是函数

我尝试过使用
Object.create(这个,Object.getOwnPropertyDescriptors(props))
而不是
Object.assign
,但结果是相同的错误

有没有办法在已克隆的对象上正确设置
super

let Moo = class {
    bar() {
        return " [bar on Moo] ";
    }
};

let Zoo = class extends Moo { 
    bar() { 
        return " [bar on Zoo] " + super.bar();
    }
};

function addProps(inst, props) {
    // Code works if the line below is commented out but otherwise
    // results in TypeError: (intermediate value).bar is not a function
    props = Object.assign({}, props); // <-- Offending code

    Object.setPrototypeOf(props, inst.__proto__);
    Object.assign(inst, props);
}

let props = {
    onZooInst: {
        bar() {
            return " [bar on overridden instance] " + super.bar();
        }
    }
};

let z = new Zoo();
addProps(z, props.onZooInst);
console.log(z.bar());
让Moo=class{
bar(){
返回“[bar on Moo]”;
}
};
让Zoo=class扩展Moo{
bar(){
返回“[bar on Zoo]”+super.bar();
}
};
功能添加道具(安装、道具){
//如果下面的行被注释掉,则代码可以工作,否则
//导致TypeError:(中间值).bar不是函数
props=Object.assign({},props);//
有没有办法在已克隆的对象上正确设置
super

let Moo = class {
    bar() {
        return " [bar on Moo] ";
    }
};

let Zoo = class extends Moo { 
    bar() { 
        return " [bar on Zoo] " + super.bar();
    }
};

function addProps(inst, props) {
    // Code works if the line below is commented out but otherwise
    // results in TypeError: (intermediate value).bar is not a function
    props = Object.assign({}, props); // <-- Offending code

    Object.setPrototypeOf(props, inst.__proto__);
    Object.assign(inst, props);
}

let props = {
    onZooInst: {
        bar() {
            return " [bar on overridden instance] " + super.bar();
        }
    }
};

let z = new Zoo();
addProps(z, props.onZooInst);
console.log(z.bar());
不。
super
使用函数的
[[HomeObject]]
插槽,该插槽在创建函数(方法)时设置,目前无法更改

关于这一点,规范中最好的引用可能是:

[[HomeObject]]
:如果函数使用
super
,则该对象的[[GetPrototypeOf]]提供了开始查找
super
属性的对象

您唯一能做的就是尝试更改函数的
[[HomeObject]]
引用的对象的原型,但A)变得丑陋快速,B)破坏性能(在重要的情况下)


如果您正在进行大量的“方法”克隆,最好使用引用函数而不是方法的简单属性,并且不要使用
super
如果正确解释需求,您可以在
props
对象中将
bar
函数调整为
this.bar()
并使用
function.prototype.call()
Function.prototype.apply()
Reflect.apply()
函数调用设置为
props.onZooInst.bar
Moo.prototype

让Moo=class{
bar(){
返回“[bar on Moo]”;
}
};
让Zoo=class扩展Moo{
bar(){
返回“[bar on Zoo]”+super.bar();
}
};
让道具={
onZooInst:{
bar(){
返回“[bar on overrided instance]”+this.bar();
}
}
};
设z=新动物园();
让reflectBar=Reflect.apply(props.onZooInst.bar,z.uu proto_uu,[]);
让callBar=props.onZooInst.bar.call(z.\uuuu proto\uuuu);
console.log(反射条);

console.log(callBar);
对于可能面临相同问题的任何人,我终于找到了解决方案

而不是像这样定义对象文本块

let a = {
    someFunc() {
        super.someFunc();
    } 
}
可以使用返回它们的箭头函数替换它们:

let a = () => {
    return {
        someFunc() {
            super.someFunc();
        } 
    }
};

这是因为
a();
?为什么要使用
class
表达式来定义
Moo
Zoo
?我正在使用ES6语法,super.bar()的目的是调用原型链中的下一个方法。
返回“[bar on overrided instance]”+super.bar();
”[bar on overrided instance][bar on Moo]的预期结果是什么 "
?如果super是动态的就好了!我将你的问题添加到这个ESDiscussion线程中:谢谢你的解释-但是为什么没有Object.assign,代码就可以工作?我的尝试基于MDN文档,但根据你的解释,它似乎没有给出完整的细节。好吧,我明白了:Object.assign没有复制方法,我t创建对它们的引用。正如您正确指出的,[[HomeObject]]设置在创建函数的位置。因此,如果我使用Object.setPrototypeOf,它对函数引用没有影响。解决方法之一是计算function.toString以创建新函数,将其放入对象中,然后对其调用setPrototypeOf,但这有点太粗糙,没有用处,并且它会在原始函数上闪现任何作用域。@Jarym:NJavaScript复制函数(除了使用通常不起作用的
toString
eval
)时,您总是在处理引用(与其他对象一样)。
var f1=function(){};
f1
中存储对函数的引用
var f2=f1;
(这基本上就是
对象.assign
所做的)将引用复制到
f2
对象。setPrototypeOf
确实会改变
条,如果应用到正确的对象(),它会被调用,但正如我所说的,它会很快变丑并破坏对象的性能。:-)谢谢,我知道我可以用不同的方式重写代码,但我想做得更好。我不得不承认目前不可能做到这一点。你是否仍在使用相同的
addProps
函数和你新的箭头函数方法?你能发布完整的代码作为你的答案吗?