2015-02-08 56 views
0

我最近開始使用traceur並偶然發現一個奇怪的行爲,當在原型上創建一個默認值的類。我想知道這是Traceur中的一個bug還是ES6類的預期行爲?es6類與原型上的默認屬性拋出traceur

class hasDefault { 
    setValue (v) { 
    this.v = v; 
    } 
} 
Object.defineProperty(hasDefault.prototype, "v", { 
    value : 5, 
    enumerable : true 
}); 

let a = new hasDefault; 
console.assert(a.v === 5); 
a.setValue(2); 
console.assert(a.v === 2); 

run in traceur REPL

它拋出,當我嘗試設置它,我不能分配給只讀屬性「V」的錯誤。這是沒有意義的,因爲該屬性是在原型上定義的,而不是實例。此外,我無法得到這個錯誤在密封/凍結/不可擴展的對象上投入es5,並且據我所知,代理不在V8中實現,所以...它如何將錯誤放在第一位?這不是編譯時錯誤。

我的主要興趣不是「讓它工作」,這是微不足道的。你所需要做的就是用Object.defineProperty代替this.v = v。我主要想知道它是否以及爲什麼會以這種方式運行,並且如果在此數據結構中存在負面的性能影響,則會通過將默認屬性分配給原型而不是將其存儲在每個實例上而超過內存增益。

回答

1

它拋出,當我嘗試設置它,我不能分配給只讀屬性「V」的錯誤。這是沒有意義的,因爲該屬性是在原型上定義的,而不是實例。

是的,該屬性是隻讀的,因爲writable屬性默認爲false。當v屬性被繼承時,該屬性對賦值也有效。

而且我無法得到這個錯誤在ES5扔

您只需要使用嚴格模式,它會做:

"use strict"; 
var test = Object.create(Object.defineProperty({}, "v", {value: 5, enumerable: true})); 
console.log(test.v) // 5 
test.v = 1; // Unhandled Error: Invalid assignment in strict mode 
+0

好的,謝謝我不知道屬性描述符在繼承時以這種方式工作,但它確實有意義。你對嚴格的模式也是正確的,這對我來說是草率的,在控制檯做了測試並忘了它:) – Winchestro 2015-02-08 13:40:47

1

如果使用Object.defineProperty指定的唯一value代替getset定義屬性,那麼你正在使用data descriptor(見here)。通過data descriptor,您可以添加writable屬性來指定屬性是否可以更改。默認writable=false

因此,如果您只指定了數據描述符的value,而沒有writable: true - 您以後不能更改該屬性。這種行爲與ES6沒有任何關係,因爲在ES5中引入了Object.defineProperty

正確的代碼:

class hasDefault { 
    setValue (v) { 
    this.v = v; 
    } 
} 
Object.defineProperty(hasDefault.prototype, "v", { 
    value : 5, 
    writable: true, 
    enumerable : true 
}); 

let a = new hasDefault; 
console.assert(a.v === 5); 
a.setValue(2); 
console.assert(a.v === 2); 

Traceur REPL

+0

謝謝,你的答案是正確的但在我的情況下,混淆更多的是關於實例描述符的繼承,而不是關於非可寫屬性本身。 – Winchestro 2015-02-08 13:50:23