《前端之路》之 JavaScript 進階技巧之高階函數(下)

第二章 - 03: 前端 進階技巧之高階函數

1、防篡改對象

JavaScript共享的本質一直是開發人員心頭的痛,由於任何對象均可以被在同一個環境中運行的代碼修改。前端

ECMAScript5致力於解決這個問題,可讓開發人員定義防篡改對象(tamper-proof object)。它的原理就是java

經過設置每一個對象的屬性的一下的默認屬性:git

  • [[Configurable]] --- 是否可配置
  • [[Writable]] --- 是否能夠從新賦值
  • [[Enumerable]] --- 是否可列舉的
  • [[Value]] --- 默認值
  • [[Get]]
  • [[Set]]

1-1:Configurable 和 Writable

下面咱們就針對以上每個屬性進行 解析一下:github

// Demo one
var o = {}
Object.defineProperty(o, 'name', {
    value: 'zhang',
    configurable: false
})
console.log(o)

Object.defineProperty(o, 'name', {
    writable: false
})

o.name = 'Li'

console.log(o)  // {name: 'zhange'}  屬性未被改變

上面的 Demo 中 咱們將 configurable 屬性設置成爲 false, 再對比下面的 Demo 來看 configurable 屬性做用瀏覽器

// Demo two
var o = {}
Object.defineProperty(o, 'name', {
    value: 'zhang',
    configurable: false
})
console.log(o)

Object.defineProperty(o, 'name', {
    writable: true
})

o.name = 'Li'
 
// Uncaught TypeError: Cannot redefine property: name 報錯

總結: 當 [[Configurable]] 爲 fasle 的時候 [[Writable]] 默認已經被設置 false, 若是去修改 [[Writable]] 的時候
則會報錯。 那麼咱們就能夠理解爲 當 [[Configurable]] 爲 false 的時候, [[Writable]] 是隻能爲 false的。函數

1-2:Enumerable

咱們仍是用 Demo 來進行對比解釋:this

var o = {}
Object.defineProperty(o, 'age', {
    enumerable: true,
    value: 18
})

for(item in o) {
    console.log(item, o[item])   // age 18
}

把 enumerable 設置成 falseprototype

var o = {}
Object.defineProperty(o, 'age', {
    enumerable: false,
    value: 19
})

for(item in o) {
    console.log(item, o[item])   // undefined
}

1-3:get 、set

get 和 set 這對雙胞胎咱們已經說過屢次了。此次咱們仔細來看下這個~code

var o = {}
var v = 'coder'
Object.defineProperty(o, 'job', {
    get: function() {
        console.log('get:', v)
        return v
    },
    set: function(newV) {
        console.log('set:', newV)
        v = newV
    }
})
o.job = 'xxx'   // set: xxx

// 很奇怪的一點就是 當咱們在 瀏覽器控制檯點開 o 對象的時候,再次去點擊 job 屬性,就會觸發 get 方法。

2-1:不可擴展對象

Object.preventExtensions(o)
可使得 不能再給對象添加屬性和方法

var o = {name: 'zhang'}
Object.preventExtensions(o)

o.age = '12'
console.log(o)      // {name: 'zhang'}

// 已經阻止了給對象添加屬性和方法了。再去添加 也未能添加上

Object.isExtensible(o)
肯定對象是否能夠擴展

var o = {name: 'zhang'}
var res1 = Object.isExtensible(o)
Object.preventExtensions(o)
var res2 = Object.isExtensible(o)
console.log(res1, res2)     // true false

2-2:密封的對象

Object.seal(o)
密封對象不可擴展,並且已有成員的[[Configurable]]特性被設置爲false,意味着不能刪除屬性和方法。不可增長,不能刪除。

var o = {name: 'Li'}
Object.isSealed(o)  // false
Object.seal(o)
Object.isSealed(o)  // true

Object.isSealed(o)
檢測時候被密封了(🐝 )

2-3:凍結的對象

Object.freeze(o)

最嚴格的防篡改級別就是凍結對象(frozen object)。凍結的對象不能擴展,又是密封的,並且對象屬性的[[Writable]]特性會被設置爲false。

若是定義了[[Set]]函數,訪問器屬性仍然是可寫的。

var obj = {age: 123}
Object.freeze(obj)
Object.isFrozen(obj)            // true
Object.isSealed(obj)            // true
Object.isExtensible(obj)        // false

Object.isFrozen(o)

檢查是否被凍結

2、自定義事件

基於 觀察者模式的一種建立鬆散耦合代碼的技術。使用自定義事件有助於解耦相關對象,保持功能的隔絕。

function EventTarget(){
    this.handlers = {};
}

EventTarget.prototype = {
    constructor : EventTraget,
    addHandler : function(type,handler){
        if(typeof this.handlers[type] === 'undefined'){
            this.handlers[type] = [];
        }
        this.handlers[type].push(handler);
    },
    fire : function(event){
        if(!event.target){
            event.target = this;
        }
        if(this.handlers[type] instanceof Array){
            var handlers = this.handlers[event.type];
            for(var i = 0,len = handlers.length; i < len; i++){
                handlers[i](event);//執行回調函數
            }
        }
    },
    removeHandler : function(type,handler){
        if(this.handlers[type] instanceof Array){
            var handlers = this.handlers[type];
            for(var i = 0,len = handlers.length; i < len; i++){
                if(handlers[i] === handler){
                    break;
                }
            }
            handlers.splice(i,1);//刪除
        }
    }
}

總結: 以上則爲高階函數中的相關的一些場景的應用,可是這也僅僅是屬於基礎部分,實際的使用場景還須要你們本身靈活處理。
好了,本期這篇 blog 就先寫到這裏。

GitHub 地址:(歡迎 star 、歡迎推薦 : )

前端 進階技巧之高階函數(下)

相關文章
相關標籤/搜索