我有以下JavaScript代码段:
RotaID,
PayperodID,
EmployeeID
RotaID
Start_dt
Finish_dt
我想知道可以用什么来代替class Foo {
constructor() {
this.b = 1;
this.getB = () => { return this.b; };
}
}
const normalFoo = new Foo();
const clonedFoo = magicClone(normalFoo);
clonedFoo.b = 5;
console.log(clonedFoo instanceof Foo); // should be true
console.log(clonedFoo.getB()); // should be 5
以获得期望的结果(例如,尊重箭头功能绑定的克隆)。
我可以接受各种可怕的黑客手段,并且我对大多数时候都可以使用的解决方案也可以,只要在这种情况下可以使用。这主要是为了我的教育:)
请不要以重复的形式关闭此问题-克隆对象已被问过很多次,但我找不到能做到这一点的单个答案。 magicClone
,lodash的Object.assign
,jQuery的克隆等都无法处理这种情况。
答案 0 :(得分:1)
因此,这里的主要挑战是您有一个箭头功能,该功能被分配为Foo
实例上的属性。由于箭头函数从其封闭的上下文继承它们的this
,并且一旦创建就无法反弹,这是让getB
引用克隆的b
的唯一方法字段是重新创建该箭头功能。这意味着您必须以某种方式调用Foo
的构造函数,以便使用正确的上下文重新创建arrow函数。
也就是说,这个magicClone
实现可以解决此示例的问题:
function magicClone(obj) {
// Manually create new instance of whatever `obj` is by invoking its constructor:
const newInstance = new obj.__proto__.constructor()
// Assign to the new instance all the non-function properties of `obj`.
Object.assign(newInstance, JSON.parse(JSON.stringify(obj)));
return newInstance;
}
但是,这种方法的主要缺点是,如果obj
的构造函数需要任何参数,则无法知道它们应该是什么。因此,这种方法依赖于您的示例Foo
类具有无参数构造函数的事实。但是,如果您可以保持这种局限性,那么它将为您带来正确的输出:
class Foo {
constructor() {
this.b = 1;
this.getB = () => { return this.b; };
}
}
function magicClone(obj) {
const newInstance = new obj.__proto__.constructor()
Object.assign(newInstance, JSON.parse(JSON.stringify(obj)));
return newInstance;
}
const normalFoo = new Foo();
normalFoo.otherProp = "must stay the same";
const clonedFoo = magicClone(normalFoo);
clonedFoo.b = 5;
console.log(clonedFoo instanceof Foo); // should be true
console.log(clonedFoo.getB()); // should be 5
console.log(clonedFoo.otherProp)
答案 1 :(得分:0)
您不能“重新绑定”箭头功能。将始终在定义它的上下文中调用它。只需使用常规功能即可。
在ArrowFunction中对参数,super,this或new.target的任何引用都必须在词汇包围的环境中解析为绑定。通常,这将是立即封闭函数的函数环境。
答案 2 :(得分:0)
从根本上讲,克隆功能是不可能的。它可能是一个闭包,我们既无法知道也无法克隆它所关闭的内容。 (箭头函数关闭其var marioToDraw = marioright;
function paint() {
if(background.loadOK) {
paper.drawImage(background.imagen, 0, 0);
}
//draw the selected Mario
paper.drawImage(marioToDraw.imagen, x, y);
}
//inside the switch statement
switch(evento.keyCode) {
case keys.RIGHT:
marioToDraw = marioright;
x = x + movement;
break;
case keys.LEFT:
marioToDraw = marioleft;
x = x - movement;
break;
default:
console.log("A different key was pressed!");
}
paint();
值只是这种情况的一种特殊情况。)
您最好的选择是使用实例实现克隆协议:
this