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 )
    

    原文地址

  • 相关阅读:
    v$、v_$、gv$之间的关系
    10046确认多块读无法跨区
    查询表Or列的注释信息
    数据文件resize扩容
    11.2.0.4rac service_name参数修改
    数据库开启对sys用户的审计
    sql查询未走索引问题分析之查询数据量过大
    ORA-00600: internal error code, arguments: [kole_t2u], [34]
    ORA-00600: internal error code, arguments: [kcblasm_1], [103], [] bug
    Linux基础知识
  • 原文地址:https://www.cnblogs.com/iron-whale/p/object_observe.html
Copyright © 2011-2022 走看看