2023年7月31日 星期一

在 Object 中定義 Property

 在 Object 中定義 Property

前言

  最近發現一般物件也可以像 Class 一樣定義 Property ,在此把學習的過程做個紀錄。


內容

  範例如下

let obj = {};
Object.defineProperty( obj , 'prop' ,{ value:10 } );
console.log( obj.prop );//10
obj.prop = 30;
console.log( obj.prop );//10
//
Object.defineProperty( obj , 'prop1' ,{
  value : 10,
  writable: true 
} );
console.log( obj.prop1 );//10
obj.prop1 = 30;
console.log( obj.prop1 );//30


要在定義 Object 中定義 Property 可以透過 Object.defineProperty() 來達成,範例開頭定義 'prop' ,直接列印後如同定義,但修改 'prop' 後發現數值遽然不能改!原因是 Object.defineProperty()  如果不刻意設定"可寫"就會是"唯讀",要如何改"可寫"呢?看範例的 'prop1',在 Object.defineProperty()  裡新增 'writable' 並設成 true,這樣就可以設定成"可寫"。


參考資料

[ developer.mozilla.org ] Object.defineProperty()

2023年7月24日 星期一

在 JavaScript 禁止物件擴充

 在 JavaScript 禁止物件擴充

前言

  最近發現 JavaScript 可以讓物件禁止擴充成員,在此把學習的過程作紀錄。


內容

  在 JavaScript 的 Object 預設是可以隨意地擴充成員的,如果想要禁止這件事是可行的嗎?答案是可行的,範例如下

let obj = {};
console.log( Object.isExtensible(obj) );//true
obj.a = 10;
console.log( obj.a );//10
Object.preventExtensions( obj );
console.log( Object.isExtensible(obj) );//false
obj.b = 0;
console.log( obj.a );//10
console.log( obj.b );//undefined


範例開頭是在 obj 下擴充 a 這個成員,接著透過 Object.preventExtensions() 來禁止擴充成員,接著再擴充成員 b ,但結果是 undefiend 。如果要確認物件是否可擴充可以透過 Object.isExtensible() 來確認,要注意的是禁止擴充後,再做擴充的行為是不會有任何的錯誤出現在 console。


參考資料

[ developer.mozilla.org ] Object.isExtensible()

2023年7月17日 星期一

覆蓋 String.replace() 對物件的行為

 覆蓋 String.replace() 對物件的行為

前言

  在研究 Symbol 時發現可以覆蓋 String.replace() 對物件的行為,在此把學習的過程做紀錄。


內容

  String.replace() 對物件的行為預設是會回傳原本的字串,透過覆蓋可以改變該行為,範例如下

class Replace1 {
  constructor(value) {
    this.value = value;
  }
  [Symbol.replace](string) {
    return `${string} replace ${this.value}`;
  }
}
let obj ={};
obj[Symbol.replace] = function(string){
  return "I am cusutom replace.";
}
console.log('foo'.replace(new Replace1('bar')));//"foo replace bar"
console.log('foo'.replace(obj) );//"I am cusutom replace."


覆蓋的做法是在要被覆蓋的物件裡定義覆蓋 function ,透過 Symbol.replace 來指名覆蓋,範例示範在 class 與 object 的覆蓋,覆蓋 function 的參數是來源的 String ,也就是喚起 replace() 的 String。


參考資料

[ developer.mozilla.org ] Symbol.replace

2023年7月10日 星期一

改變 Array.concat() 的特性

 改變 Array.concat() 的特性

前言

  最近學習 Symbol 時發現它可以改變Array.concat() 的特性,在此把學習的過程做紀錄。

 

內容

  範例如下

let strAr = [ 'a' , 'b' , 'c' ];
let numAr1 = [ 1 , 2 , 3 ];
let numAr2 = [ 4 , 5 , 6 ];
console.log( strAr.concat(numAr1) );//["a", "b", "c", 1, 2, 3]
//
numAr1[ Symbol.isConcatSpreadable ] = false;
console.log( strAr.concat(numAr1) );//["a", "b", "c", [1, 2, 3]]
console.log( strAr.concat(numAr2) );//["a", "b", "c", 4, 5, 6]


範例開頭先示範一次正常的 Array.concat() ,接著透過 Symbol.isConcatSpreadable 這個 Symbol 來存取 Array 的特性,改變後再次 Array.concat() 後發現 Array 不會被展開了!要注意這個改變特性是針對個別的 Array 來修改,所以與 numAr2 執行 Array.concat()  又再次展開了。Symbol 可以用來改變改變 Function 的行為,用起來雖然優美,但這是不是也代表著以後這些 Funciton 不能認定它只有一種行為,個人認為透過提供新的 Method 或讓 Function 可以用參數來調整行為的做法是比較好的。


參考資料

[ developer.mozilla.org ] Symbol.isConcatSpreadable

2023年7月3日 星期一

使用 global 的 Symbol

 使用 global 的 Symbol

前言

  在先前的 JavaScript 的 Symbol 入門 提到 Symbol 的基本運用,這次來學習 global 的運用,在此把學習的過程做個紀錄。


內容

  使用 Symbol() 所得到的 Symbal 都是個別的,如果要隨時可以取得同一個 Symbal 的話可以透過 Symbal.for() 來取得同一個 Symbal ,範例如下

let globalSymbol = Symbol.for('foo');
let localSymbol = Symbol('foo');
console.log( globalSymbol === localSymbol );//false
console.log( globalSymbol === Symbol.for('foo') );//true
console.log( localSymbol === Symbol.for('foo') );//false
//
console.log( Symbol.keyFor(globalSymbol) );//"foo"
console.log( Symbol.keyFor(localSymbol) );//undefined


範例開頭有透過 Symbol.for() 來取得的 globalSymbal 與透過 Symbol() 取得的 localSymbal ,可以發現 globalSymbal  與 localSymbal  是不同一個,但如果再次透過 Symbal.for() 用同一名稱取得會發現它與 globalSymbal  是同一個 Symbal !但用類似的手法用在 Symbal() 結果卻不同,也不難理解,因為 Symbal() 每次取得都是獨立的 Symbal。global 的 Symbal 是透過 key 來取得 Symbal ,那如果需要透過 Symbal 來取得 Key 可能嗎?可以透過 Symbal.keyFor() 來達成,不過要注意一下如果用 local 的 Symbal 來查詢時回傳的結果會是 undefined!


參考資料

[ developer.mozilla.org ] Symbol


相關文章與資料

JavaScript 的 Symbol 入門