zoukankan      html  css  js  c++  java
  • 使用原生 js 模拟被废弃的 Object.observe()

    写了两个版本,分别是使用 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 )
    

    原文地址

  • 相关阅读:
    archlinux .bash_history
    Ubuntu环境下挂载新硬盘
    软碟通 UltraISO U启替代品 Win32DiskImager 无设备 无盘符 无u盘 无优盘 解决方案 之diskpart
    delphi Integer overflow
    MSBuild Tools offline
    delphi synedit免费的拼写检查器dll
    git 自定义命令行
    lua编译
    gcc ar
    Windows Subsystem for Linux (WSL)挂载移动硬盘U盘 卸载 c d 盘
  • 原文地址:https://www.cnblogs.com/iron-whale/p/object_observe.html
Copyright © 2011-2022 走看看