0

如何在无法访问 object.defineProperty 的情况下使用装饰器?

我正在研究可用的垫片:

但如果那些没有通过测试,装饰器是否有另一种工作方式?

我正在为$onRootScope使用装饰器。

我正在使用角度 1.08。我需要兼容 IE7。

更新

我尝试了一些似乎有效的方法,但我不知道它们之间的区别:plunkr

var app = angular.module('plunker', []);

app.config(['$provide', function($provide){
  $provide.decorator('$rootScope', ['$delegate', function($delegate){
    $delegate.a = 1;
    $delegate.constructor.prototype.b = 2;
    Object.defineProperty($delegate.constructor.prototype, 'c', {
      value: 3
    });
    return $delegate;
  }]);
}]);

app.controller('MainCtrl', function($rootScope, $scope) {
  console.log($rootScope);   //reveals `a` property
  console.log($rootScope.constructor.prototype); //=> {b:2, c:3}
  console.log($rootScope.a); //=> 1
  console.log($rootScope.b); //=> 2
  console.log($rootScope.c); //=> 3
  $scope.name = 'World';
});

谢谢你。

4

1 回答 1

0

好吧,您共享的代码的等效解决方案是:

var proto = Object.getPrototypeOf(Object.getPrototypeOf($delegate));
proto['$onRootScope'] = function (name, listener) {
   var unsubscribe = $delegate.$on(name, listener);
   this.$on('$destroy', unsubscribe);
};

在原始代码中,这一行$delegate.constructor.prototype可以访问 $delegate 的原型原型。

然后,一旦您可以访问它,您就可以简单地在其中定义一个新函数。您不需要使用defineProperty. 唯一需要注意的是,通过使用,defineProperty您可以配置该方法不可枚举(不应出现在 for-each 循环中)。以这种方式,添加的方法将出现在 for-each 循环中。不过,这对您来说可能不是问题。

我为此创建了一个JSFiddle

如果该功能不适用于您当前的浏览器,您可以使用John Resig 的 polyfill :getObjectPrototypeOf

if ( typeof Object.getPrototypeOf !== "function" ) {
  if ( typeof "test".__proto__ === "object" ) {
    Object.getPrototypeOf = function(object){
      return object.__proto__;
    };
  } else {
    Object.getPrototypeOf = function(object){
      // May break if the constructor has been tampered with
      return object.constructor.prototype;
    };
  }
}
于 2014-02-28T16:36:43.380 回答