如何在不访问object.defineProperty的情况下使用装饰器?
我正在研究可用的垫片:
ES5,假 填充工具但是如果那些没有通过测试,装饰者是否还有另外一种工作方式?
我正在使用$ 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'; });谢谢。
How do I use decorators without having access to object.defineProperty?
I am looking into the shims available:
es5-sham polyfillbut in case those don't pass testing, is there another way decorators were intended to work?
I am using the decorator for $onRootScope.
I am using angular 1.08. I need compatibility with IE7.
Update
I have tried out a few methods that seem to work but I don't know the difference between them: 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'; });Thank You.
最满意答案
那么,您共享的代码片段的等效解决方案是:
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; }; } }
Well, an equivalent solution to the pice of code you shared is:
var proto = Object.getPrototypeOf(Object.getPrototypeOf($delegate)); proto['$onRootScope'] = function (name, listener) { var unsubscribe = $delegate.$on(name, listener); this.$on('$destroy', unsubscribe); };In the original code this line $delegate.constructor.prototype is getting access to the $delegate's prototype prototype.
Then, once you get access to it, you can simply define a new function in it. You do not need to use defineProperty. The only caveat is that by using defineProperty you can configure that the method is not enumerable (should not appear in for-each loops). In this other way, the method added would appear in for-each loops. It may not be a problem for you though.
I have created a JSFiddle for this.
You can use John Resig's polyfill for getObjectPrototypeOfif the function is not available for your current browser:
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; }; } }
更多推荐
发布评论