• 使用原生 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 )
    

    原文地址

  • 相关阅读:
    26个精选的JavaScript面试问题
    用js实现随机选取10–100之间的10个数字,存入一个数组,并排序
    小程序布局中class='container'的bug
    PHP接收数据数据包的几个方式
    LINUX命令
    VMware的下载安装
    php中Sessions
    php中Cookies
    php文件上传
    php文件处理
  • 原文地址:https://www.cnblogs.com/iron-whale/p/object_observe.html
Copyright © 2020-2023  润新知