docs: function(fn){
        // obsolete in 1.4
        /** @cut */ if (arguments.length > 1)
        /** @cut */   basis.dev.warn('basis.data.Value#as() doesn\'t accept deferred flag as second parameter anymore. Use value.as(fn).deferred() instead.');
  
        if (!fn || fn === $self)
          return this;
  
        if (typeof fn == 'string')
          fn = basis.getter(fn);
  
        if (this.links_)
        {
          // try to find value with the same function
          var cursor = this;
          var fnId = fn[GETTER_ID] || String(fn);
  
          while (cursor = cursor.links_)
          {
            var context = cursor.context;
            if (context instanceof ReadOnlyValue &&
                context.proxy &&
                (context.proxy[GETTER_ID] || String(context.proxy)) == fnId) // compare functions by id
            {
              /** @cut */ context = devWrap(context);
  
              return context;
            }
          }
        }
  
        // create transform value
        var result = new ReadOnlyValue({
          proxy: fn,
          value: this.value
        });
  
        /** @cut */ basis.dev.setInfo(result, 'sourceInfo', {
        /** @cut */   type: 'Value#as',
        /** @cut */   source: this,
        /** @cut */   sourceTarget: this.value,
        /** @cut */   transform: fn
        /** @cut */ });
  
        /** @cut */ if (fn.retarget)
        /** @cut */ {
        /** @cut */   result.proxy = function(value){
        /** @cut */     value = fn(value);
        /** @cut */     basis.dev.patchInfo(result, 'sourceInfo', {
        /** @cut */       sourceTarget: value
        /** @cut */     });
        /** @cut */     return value;
        /** @cut */   };
        /** @cut */   result.proxy[GETTER_ID] = fn[GETTER_ID]; // set the same GETTER_ID for correct search in links_
        /** @cut */ }
  
        this.link(result, valueSyncAs, true, result.destroy);
  
        return result;
      }