tho*_*phn 4 coffeescript angularjs
使用CoffeeScript,Angular和$ resource,我创建了以下工厂:
angular.module('myapp', ['ngResource']).factory 'MyObject', ['$resource', ($resource) ->
MyObjectResource = $resource '/api/my_object/:id', {
id: '@id'
}, {
update:
method: 'PUT'
}
class MyObject extends MyObjectResource
someMethod: ->
dosomething
]
Run Code Online (Sandbox Code Playgroud)
问题是当我从API加载一个对象时,我得到一个Resource 对象而不是一个MyObject对象,这是一个问题,因为我无法访问我的其他方法.
这是我获取对象的代码:
result = MyObject.get({id: 1})
Run Code Online (Sandbox Code Playgroud)
如果我打印result,我可以看到:
Resource {id: 1, details: 'somestuff'}
Run Code Online (Sandbox Code Playgroud)
相比之下,我希望有:
MyObject {id: 1, details: 'somestuff'}
Run Code Online (Sandbox Code Playgroud)
这将使我能够访问someMethod我为此课程定义的所有其他方法.
难道我做错了什么?
提前致谢.
快速查看源代码后,我看到以下关系:
Resource在工厂内部(它是$resource提供者)创建了一个函数,并在$resource调用时返回.资源具有以下结构(让我们想象一下,我们只想获得它所拥有的方法的高级视图,而不是每个方法的工作方式)
function Resource(value) { ... }
Resource.prototype.toJSON = function () { ... }
Resource.prototype.bind = function () { ... }
Run Code Online (Sandbox Code Playgroud)
$resource函数在第3个参数中接收要在函数上设置的附加动作(与某些默认动作合并)Resource,我看到你正在发送一个额外的update方法,所以该对象具有以下结构合并update默认操作:
{
'get': {method: 'GET'},
'save': {method: 'POST'},
'query': {method: 'GET', isArray: true},
'remove': {method: 'DELETE'},
'delete': {method: 'DELETE'},
// added by the user
update: { method: 'PUT' }
}
Run Code Online (Sandbox Code Playgroud)
$resource为Resource函数上的这个散列的每个属性设置一个方法,也Resource为$在方法名称之前附加a 的原型设置一个方法,即
Resource.get = function () { ... }
Resource.save = function () { ... }
Resource.update = function () { ... }
...
Resource.prototype.$get = function () { ... }
Resource.prototype.$save = function () { ... }
Resource.prototype.$update = function () { ... }
...
Run Code Online (Sandbox Code Playgroud)
现在回到你的代码中正在延伸的新功能MyObject从MyObjectResource哪里MyObjectResource是调用的结果,$resource也就是Resource上面看到,CoffeeScript中的功能extend实际上将复制上定义的所有属性MyObjectResource来MyObject,也使隐藏[[Prototype]]的属性MyObject.prototype点MyObjectResource.prototype:
MyObjectResource
prototype -------> MyObjectResource.prototype
$get
get $save
save toJSON
... ...
^
|
MyObject |
prototype -------> MyObject.prototype
get (reference) someMethod
set (reference)
...
Run Code Online (Sandbox Code Playgroud)
所以这就是你可以做的MyObject.get原因,因为它现在有一个参考MyObjectResource.get,即MyObject.get === MyObjectResource.get
这是有趣的部分,调用MyObject.get将返回一个实例MyObjectResrouce(这实际上是被编码的,但只有在内部MyObject.get this不是MyObjectResource Source的实例时才会发生),如果我们这样做new MyObjectResource()是无法访问的,someMethod因为它实际上是在"子类"中定义的.
但是我们可以创建一个实例,MyObject并且由于coffeescript创建的链接extend,实例可以访问相同的get通过MyObjectResource.prototype.$get,所以:
var instance = new MyObject()
instance.$get({id: 1}); // works because of the link created between the prototypes
instance.someMethod(); // also works
Run Code Online (Sandbox Code Playgroud)