美文网首页web 杂谈让前端飞技术干货
使用原生 js 模拟被废弃的 Object.observe()

使用原生 js 模拟被废弃的 Object.observe()

作者: 高少辉_骚辉 | 来源:发表于2017-07-27 16:19 被阅读851次

    写了两个版本,分别是使用 js 里的 Proxy (代理)和 Object.defineProperty 实现

    两个版本都有各自的缺陷,大家可以按需自己选择自己需要的

    • Proxy 不能监听源对象,只能监控代理对象
    • Object.defineProperty 有新增属性的时候,无法做到自动监听

    Proxy

    /**
     * 使用 Proxy 来说实现被废弃的 Object.observe()
     * 
     * @param {any} target 
     * @param {any} fnBind 
     * @returns 
     */
    var bind = function ( target, fnBind ) {
        bind.targets = bind.targets || []
        var targets = bind.targets
        ,   index = targets.indexOf( target )
    
        bind.fnBinds = bind.fnBinds || []
        var fnBinds = bind.fnBinds
        if( index == -1 ) {
            index = targets.length
            targets.push( target )
            fnBinds.push( [] )
        }
        var targetFnBinds = fnBinds[index]
        targetFnBinds.push( fnBind )
    
      bind.proxy = bind.proxy || new Proxy( target, {
        set: function ( target, prop, value ) {
                target[prop] = value
          for( var i = 0; i < targetFnBinds.length; i ++ ) {
            targetFnBinds[i].call( target )
          }
        }
      } )
      return bind.proxy
    }
    
    var person = {
      name: '12'
      ,age: '23'
    }
    var child = bind( person, function () {
      console.log( 'bind: ', this.name )
    } )
    person.name = 333
    child.name = 444
    console.log( person )
    console.log( child )
    

    Object.defineProperty

    /**
     * 使用 es5 的 Object.defineProperty 特性 来实现 Object.observe()
     * 
     * @param {any} target 
     * @param {any} fnBind 
     * @returns 
     */
    var bind = function ( target, fnBind ) {
        bind.targets = bind.targets || []
        bind.cloneTargets = bind.cloneTargets || []
        var targets = bind.targets
        , closeTargets = bind.cloneTargets
        ,   index = targets.indexOf( target )
    
        bind.fnBinds = bind.fnBinds || []
        var fnBinds = bind.fnBinds
        if( index == -1 ) {
            index = targets.length
            targets.push( target )
            closeTargets.push( Object.assign( {}, target ) )
            fnBinds.push( [] )
        }
        var targetFnBinds = fnBinds[index]
        targetFnBinds.push( fnBind )
    
        for( var prop in target ) {
            Object.defineProperty( target, prop, {
                set: function ( val ) {
                    closeTargets[index][prop] = val
                    for( var i = 0; i < targetFnBinds.length; i ++ ) {
                        targetFnBinds[i].call( target )
                    }
                },
                get: function () {
                    return closeTargets[index][prop]
                }
            } )
        }
    
      return target
    }
    
    var person = {
      name: '12'
      ,age: '23'
    }
    var child = bind( person, function () {
      console.log( 'bind: ', this.name )
    } )
    person.name = 333
    child.name = 444
    child.name = 555
    console.log( person )
    console.log( child )
    

    相关文章

      网友评论

        本文标题:使用原生 js 模拟被废弃的 Object.observe()

        本文链接:https://www.haomeiwen.com/subject/rlnzkxtx.html