Symbol的特性

 Symbol的應用場景

下面是幾個Symbol在程序中的應用場景。

應用一:防止XSS

ReactReactElement對象中,有一個$$typeof屬性,它是一個Symbol類型的變量:

var REACT_ELEMENT_TYPE =
  (typeof Symbol === 'function' && Symbol.for && Symbol.for('react.element')) ||
  0xeac7;

ReactElement.isValidElement函數用來判斷一個React組件是否是有效的,下面是它的具體實現。

ReactElement.isValidElement = function (object) {
  return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;
};

可見React渲染時會把沒有$$typeof標識,以及規則校驗不通過的組件過濾掉。

如果你的服務器有一個漏洞,允許用戶存儲任意JSON對象, 而客戶端代碼需要一個字符串,這可能會成爲一個問題:

// JSON
let expectedTextButGotJSON = {
  type: 'div',
  props: {
    dangerouslySetInnerHTML: {
      __html: '/* put your exploit here */'
    },
  },
};
let message = { text: expectedTextButGotJSON };
<p>
  {message.text}
</p>

JSON中不能存儲Symbol類型的變量,這就是防止XSS的一種手段。

應用二:私有屬性

藉助Symbol類型的不可枚舉,我們可以在類中模擬私有屬性,控制變量讀寫:

const privateField = Symbol();
class myClass {
  constructor(){
    this[privateField] = 'ConardLi';
  }
  getField(){
    return this[privateField];
  }
  setField(val){
    this[privateField] = val;
  }
}

應用三:防止屬性污染

在某些情況下,我們可能要爲對象添加一個屬性,此時就有可能造成屬性覆蓋,用Symbol作爲對象屬性可以保證永遠不會出現同名屬性。

例如下面的場景,我們模擬實現一個call方法:

    Function.prototype.myCall = function (context) {
      if (typeof this !== 'function') {
        return undefined; // 用於防止 Function.prototype.myCall() 直接調用
      }
      context = context || window;
      const fn = Symbol();
      context[fn] = this;
      const args = [...arguments].slice(1);
      const result = context[fn](...args);
      delete context[fn];
      return result;
    }

我們需要在某個對象上臨時調用一個方法,又不能造成屬性污染,Symbol是一個很好的選擇。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章