{"action":"created","issue":{"url":"https://api.github.com/repos/kuitos/angular-es-utils/issues/7","repository_url":"https://api.github.com/repos/kuitos/angular-es-utils","labels_url":"https://api.github.com/repos/kuitos/angular-es-utils/issues/7/labels{/name}","comments_url":"https://api.github.com/repos/kuitos/angular-es-utils/issues/7/comments","events_url":"https://api.github.com/repos/kuitos/angular-es-utils/issues/7/events","html_url":"https://github.com/kuitos/angular-es-utils/issues/7","id":189944544,"number":7,"title":"关于装饰器 Inject 实现问题","user":{"login":"hjzheng","id":4166657,"avatar_url":"https://avatars.githubusercontent.com/u/4166657?v=3","gravatar_id":"","url":"https://api.github.com/users/hjzheng","html_url":"https://github.com/hjzheng","followers_url":"https://api.github.com/users/hjzheng/followers","following_url":"https://api.github.com/users/hjzheng/following{/other_user}","gists_url":"https://api.github.com/users/hjzheng/gists{/gist_id}","starred_url":"https://api.github.com/users/hjzheng/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hjzheng/subscriptions","organizations_url":"https://api.github.com/users/hjzheng/orgs","repos_url":"https://api.github.com/users/hjzheng/repos","events_url":"https://api.github.com/users/hjzheng/events{/privacy}","received_events_url":"https://api.github.com/users/hjzheng/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":4,"created_at":"2016-11-17T05:45:27Z","updated_at":"2016-11-17T11:03:57Z","closed_at":null,"body":"首先 Inject 的实现非常巧妙，解决了 AngularJS 1.x 的依赖注入，并且将依赖注入的服务，挂载到原构造函数的 prototype 上，方便使用。但是由于 Inject 装饰器返回了新的 class，导致一块使用的装饰器无法拿到原构造函数信息。另外 Inject 也不支持继承。\r\n\r\n可以通过 Proxy 去装饰原构造函数而无需使用新 class 的方式。\r\n\r\n```js\r\nconst toString = Object.prototype.toString;\r\n\r\nexport const Inject = (...dependencies) => (originTarget) => {\r\n\r\n\t// 获取当前 class 的父类\r\n\tconst parentClass = Object.getPrototypeOf(originTarget);\r\n\r\n\tconst parentDependencies = parentClass.$inject;\r\n\r\n\tif (parentDependencies && toString.call(parentDependencies) === '[object Array]') {\r\n\t\tdependencies = [...dependencies, ...parentDependencies];\r\n\t}\r\n\r\n\toriginTarget.$inject = dependencies;\r\n\r\n        // 使用 Proxy 修改构造函数\r\n\tconst handler = {\r\n\t\tconstruct(target, argumentsList) {\r\n\t\t\tdependencies.forEach((dependence, index) => {\r\n\t\t\t\ttarget.prototype[`_${dependence}`] = argumentsList[index];\r\n\t\t\t});\r\n\t\t\treturn Reflect.construct(target, argumentsList);\r\n\t\t}\r\n\t};\r\n\r\n\tconst newTarget = new Proxy(originTarget.prototype.constructor, handler);\r\n\r\n\treturn newTarget;\r\n};\r\n``` "},"comment":{"url":"https://api.github.com/repos/kuitos/angular-es-utils/issues/comments/261218888","html_url":"https://github.com/kuitos/angular-es-utils/issues/7#issuecomment-261218888","issue_url":"https://api.github.com/repos/kuitos/angular-es-utils/issues/7","id":261218888,"user":{"login":"kuitos","id":5206843,"avatar_url":"https://avatars.githubusercontent.com/u/5206843?v=3","gravatar_id":"","url":"https://api.github.com/users/kuitos","html_url":"https://github.com/kuitos","followers_url":"https://api.github.com/users/kuitos/followers","following_url":"https://api.github.com/users/kuitos/following{/other_user}","gists_url":"https://api.github.com/users/kuitos/gists{/gist_id}","starred_url":"https://api.github.com/users/kuitos/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kuitos/subscriptions","organizations_url":"https://api.github.com/users/kuitos/orgs","repos_url":"https://api.github.com/users/kuitos/repos","events_url":"https://api.github.com/users/kuitos/events{/privacy}","received_events_url":"https://api.github.com/users/kuitos/received_events","type":"User","site_admin":false},"created_at":"2016-11-17T11:03:57Z","updated_at":"2016-11-17T11:03:57Z","body":"1. 现在的实现，会 copy 原构造函数的静态属性给返回的 class，你要的信息能拿到\r\n2. 如果要做这种事情，需要去一层层分析原型链，找出每一层构造函数的依赖列表。然后：\r\n  1. 将所有父级的依赖列表 concat 到目标class 上，然后统一由目标 class 初始化。这样做简单但是不符合 extends 的行为语义。\r\n  2. 符合语义的做法是，将每一层的父类单独初始化绑定到前一个类的prototype上，实现上问题很多比如这样被继承的类只能注入全局的服务，临时服务无法注入。问题很多几乎不可行。\r\n  3. 最主要的是，前端开发中，组合 > mixin > 继承。耦合由低到高，继承几乎是最不可取的做法。\r\n3. 记忆中 proxy 的问题不止 toString，在框架下用 proxy 风险很多，不过具体你可以试下。"}}
{"actor":{"display_login":"kuitos"}}