簡體   English   中英

如何在JavaScript中使用箭頭函數克隆對象?

[英]How to clone an object with an arrow function in JavaScript?

我有這段JavaScript代碼:

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以獲得所需的結果(例如,一個尊重箭頭功能綁定的克隆)。

我對任何類型的可怕黑客都很好,只要他們在這種情況下工作,我也可以使用大多數時間都有效的解決方案。 這主要是為了我的啟發:)


請不要將此問題作為副本關閉 - 克隆對象已被多次詢問,但我找不到單一的答案。 Object.assign ,lodash的cloneDeep ,jQuery的克隆等都不處理這種情況。

所以這里的主要挑戰是你有一個箭頭函數,它被指定為你的Foo實例的屬性。 由於箭頭功能繼承this從他們的包圍下, 他們不能反彈一旦建立 ,只有這樣才能有getB引用克隆的b字段是重新創建箭頭功能。 這意味着你必須以某種方式調用Foo的構造函數,以便使用正確的上下文重新創建箭頭函數。

也就是說,這個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) 

克隆函數根本不可能。 它可能是一個封閉,我們既不知道也不能克隆它所關閉的東西。 (箭頭函數關閉它們的this值只是一個特例)。

您最好的選擇是實例實施克隆協議:

class Foo {
    constructor() {
        this.b = 1;
        this.getB = () => { return this.b; };
    }
    clone() {
        return new Foo // usually passing the current instance's state as arguments
    }
}
function magicClone(o) {
    if (Object(o) !== o) return o; // primitive value
    if (typeof o.clone == "function") return o.clone(); // if available use it
    return Object.assign(Object.create(Object.getPrototypeOf(o)), o); // shallow copy
}

const normalFoo = new Foo();
const clonedFoo = magicClone(normalFoo);

你不能“重新綁定”箭頭功能。 它將始終使用定義它的上下文進行調用。 只需使用正常功能。

來自ECMAScript 2015規范

對ArrowFunction中的arguments,super,this或new.target的任何引用都必須解析為詞法封閉環境中的綁定。 通常,這將是直接封閉函數的函數環境。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM