我对Angular.js
非常陌生,我正在努力学习它,我需要根据我们已经提出的一些新要求调整我的一些项目以适应它。
我的一个主要问题是我需要在许多页面上重现某些行为,这是一个典型的base model -> inheritance
问题。这是先前在Typescript
中通过使用自然类并扩展它们来完成的。
在研究Angular时,我了解到它并没有真正开箱即用。所以我已经对许多不同的教程进行了抽样,并且遇到了 this one in particular ,这非常有见地,非常有趣。
我试图自己重现它,使用一些稍微不同的布局和语法来试图理解它。但我似乎无法让行为得到匹配...我所做的最大改变是我没有把所有东西“链接”在一起,而是在我第一次拾取角度时学习的路线,然后声明一个变量来添加像这样的所有控制器和工厂;
var app = angular.module("MyApp", []);
app.controller('...', function($scope, ... );
app.factory('...', function($http, ...);
我已经多次查看了我的代码,并检查了它,仔细检查了它,三重检查了它,但是当我运行它时,它不起作用。如果我在最终的 jsFiddle 中复制/粘贴确切的代码,它会正常工作,所以我100%肯定我在某个地方犯了错误。
我在这里发布自己的代码,希望有人可以告诉我我做错了什么 - 因为我现在真的很失落。我还包括一个分叉的 jsFiddle 我自己的代码,以便于运行和比较。
我希望我能列出我得到的确切错误,但我不确定。实际上有很多奇怪的输出回到angular.js
文件,而不是我自己的文件,所以我不知道我自己的代码中的错误在哪里。
(function() {
var app = angular.module('MyApp', []);
app.factory('SimpleGithubUser', function($http) {
var apiUrl = 'https://api.github.com/';
// instantiate our initial object
var SimpleGithubUser = function( username ) {
this.username = username;
this.profile = null;
};
// define the getProfile method which will fetch data
// from GH API and *returns* a promise
SimpleGithubUser.prototype.getProfile = function(){
// generally, javascript callbacks, like here the $http.get callback,
// change the value of the 'this' variable inside it
// so we need to keep a reference to the current instance of 'this'
var self = this;
return $http.get(apiUrl + 'users/' + this.username).then(function(response){
// when we get the results, we store the data in user.profile
self.profile = response.data;
// promises success should always return something in order to allow chaining
return response;
});
};
return SimpleGithubUser;
});
app.factory('AdvancedGithubUser', function($http, SimpleGithubUser){
var apiUrl = 'https://api.github.com/';
// create our new custom object that reuse the original object constructor
var AdvancedGithubUser = function(){
SimpleGithubUser.apply(this, arguments);
};
// reuse the original object prototype
AdvancedGithubUser.prototype = new SimpleGithubUser();
// define a new internal private method for this object
function getUserEvents() {
var self = this;
return $http.get(apiUrl + 'users/' + this.username + '/events').then(function(response){
// attach the events API result to our user profile
self.profile.events = response.data;
// promises should always return a result
return response;
});
}
// now let's override our original getProfile method
AdvancedGithubUser.prototype.getProfile = function(){
var self = this;
// we first call the original getProfile method (aka super method)
var originalGetProfile = SimpleGithubUser.prototype.getProfile.apply(this, arguments);
// we use promises chaining to add additional data
return originalGetProfile.then(function(){
// beforer returning the results,
// call our new private method and bind 'this' to 'self'
// we need to do this because the method is not part of the prototype
return getUserEvents(self);
});
};
return AdvancedGithubUser;
});
app.service('MyUserProfile', function(AdvancedGithubUser){
var user = new AdvancedGithubUser('revolunet');
user.getProfile();
return user;
});
app.controller('MyCtrl', function(MyUserProfile){
$scope.user = MyUserProfile;
alert(MyUserProfile.location);
});
app.controller('DemoCtrl', function($scope, SimpleGithubUser, AdvancedGithubUser){
$scope.users = [];
$scope.fetchUsers = function(){
$scope.users = [];
var users = ['mhevery', 'igorminar', 'btford', 'substack', 'sindresorhus', 'n1k0', 'revolunet'];
users.forEach(function(userName){
var user = new AdvancedGithubUser(userName);
user.getProfile().then(function(){
$scope.users.push(user);
});
})
}
})
})();
<div ng-app="MyApp" ng-controller="DemoCtrl">
<h1>{{ welcome }}</h1>
<button ng-click="fetchUsers()">fetch some badass GitHub users data</button>
<ul>
<li ng-class="{odd: $odd}" ng-repeat="user in users">
<img class="gravatar" ng-src="{{ user.profile.avatar_url }}" /> <b>{{ user.profile.login }}</b> ({{ user.profile.location }})
<div class="event">{{ user.profile.events[0].type }} : {{ user.profile.events[0].repo.name }}</div>
</li>
</ul>
</div>
答案 0 :(得分:1)
来自revolunet博客的Julien:)
好吧,在您的代码中,您只是在我的示例中使用return getUserEvents(self);
时调用return getUserEvents.call(self);
。区别在于this
函数中的getUserEvents
。
在您的情况下,它将是window
,它没有任何profile.events
,这会导致您的错误,而在我的情况下,我强制它成为当前的AdvancedGithubUser
实例,这要归功于call
函数,用于更改函数调用中的this
值。
javascript中的this
行为可能非常令人困惑;它不取决于它的位置,而是取决于你使用它的上下文。
这是一篇关于这个主题的好文章:http://javascriptissexy.com/understand-javascripts-this-with-clarity-and-master-it/