变量绑定/第一个 class 函数是否优于私有方法命名?提升如何受到影响?
Are variable bound / 1st class functions preferable over private method naming? How is hoisting affected?
关于构建 Angular 代码和 JavaScript 使用变量绑定与私有方法命名函数约定时的行为的几个问题。在 AngularJS 中通过私有方法命名使用变量绑定函数/第一个 class 函数是否有性能或风格原因?提升在每种方法中是如何受到影响的?下面的第二种方法会减少执行的提升量吗?这会对应用程序性能产生显着影响吗?
一个私有方法命名的例子。这是构造 Angular 代码的推荐方法吗?
(function () {
'use strict'
function modalController(dataItemsService, $scope) {
var vm = this;
function _getSelectedItems() {
return dataItemsService.SelectedItems();
}
function _deleteSelectedItems() {
dataItemService.DeleteItem();
$("#existConfirmDialog").modal('hide');
}
vm.SelectedItems = _getSelectedItems;
vm.deleteItemRecord = _deleteItemRecord;
}
angular.module('app').controller('modalController', ['dataItemService', '$scope', modalController]
})();
变量绑定函数的一个例子。这种在控制器中构建 angular 代码的方法怎么样 - 在 performance/style 方面有什么缺点或优点吗?
angular.module('appname').controller("NameCtrl", ["$scope", "$log", "$window", "$http", "$timeout", "SomeService",
function ($scope, $log, $window, $http, $timeout, TabService) {
//your controller code
$scope.tab = 0;
$scope.changeTab = function(newTab){
$scope.tab = newTab;
};
$scope.isActiveTab = function(tab){
return $scope.tab === tab;
};
}
]);
第一种方法使用“私有”方法并通过 public 别名公开它们,称为 Revealing Module Pattern,尽管在示例中这些方法实际上并不是私有的。
后者是一个相当标准的 Constructor Pattern,使用 $scope 作为上下文。
Is there a performance or stylistic reason for using variable
bound functions / first class functions in AngularJS over private method naming?
Is [there] a recommended way to structure Angular code?
TL;DR
从根本上来说,这两种风格并没有太大区别
多于。一个使用 $scope
,另一个使用 this
。一个构造函数定义在闭包中,一个定义在行内。
有些情况下您可能需要私有方法或值。
还有风格和(可能微不足道的)表现
在 $scope
上使用变量 this
/vm
的原因。这些并不相互排斥。
您可能想要使用
基本的,基本的,老派的构造函数模式,以及很多
人们通过 this
而不是 $scope
.
公开状态和行为
您可以在 Controller 中允许自己的数据隐私,但大多数
Service/Factory 应该利用这个时间。主要的例外是代表视图状态的数据。
请不要在您的控制器中使用 jQuery。
参考文献:
AngularJS Style Guide 托德座右铭。
要彻底回答您的问题,我认为了解 Controller 的职责很重要。每个控制器的工作是向视图公开一组严格的状态和行为。简而言之,只分配给 this
或 $scope
您不介意用户在您的视图中看到或玩的东西。
问题中的 variable
(vm
, $scope
) 是由 Controller 函数创建的实例的上下文 (this
)。
$scope
是Angular的“特殊”语境;它已经定义了一些行为供您使用(例如 $scope.$watch)。 $scopes
也遵循继承链,即 $scope 继承分配给其父 $scope 的状态和行为。
拿这两个控制器:
angular.module("Module")
.controller("Controller", ["$scope", function($scope) {
$scope.tab = 0;
$scope.incrementTab = function() {
$scope.tab++;
};
}])
.controller("OtherController", ["$scope", function($scope) {
// nothing
}]);
还有风景
<div ng-controller="Controller">
<p>{{ tab }}</p>
<button ng-click="incrementTab();">Increment</button>
<div ng-controller="OtherController">
<p>{{ tab }}</p>
<button ng-click="incrementTab();">Increment</button>
</div>
</div>
示例here
你会注意到,即使我们没有在 OtherController 中定义 $scope.tab
,它也从 Controller 继承了它,因为 Controller 是它在 DOM 中的父级。在显示选项卡的两个地方,您应该看到“0”。这可能是您所指的 "hoisting",尽管那是一个完全不同的概念。
单击第一个按钮时会发生什么?在我们暴露“制表符”的两个地方,它们现在将显示“1”。当您按下第二个按钮时,两者也会更新和递增。
当然,我很可能不希望我的子选项卡与父选项卡具有相同的选项卡值。如果将 OtherController 更改为:
.controller("OtherController", ["$scope", function($scope) {
$scope.tab = 42;
}]);
您会注意到此行为已发生变化 - 选项卡的值不再同步。
但现在很混乱:我有两个叫做“制表符”的东西是不一样的。其他人可能稍后使用“tab”写了一些代码并无意中破坏了我的代码。
我们过去常常通过在 $scope
上使用命名空间来解决这个问题,例如$scope.vm
并将所有内容分配给命名空间:$scope.vm.tab = 0;
<div ng-controller="OtherController">
<p>{{ vm.tab }}</p>
<button ng-click="vm.incrementTab();">Increment</button>
</div>
另一种方法是使用 this
的简单性和简洁性,并利用 controllerAs 语法。
.controller("OtherController", function() {
this.tab = 0;
});
<div ng-controller="OtherController as oc">
<p>{{ oc.tab }}</p>
</div>
对于习惯使用普通 JS 的人来说,这可能会更舒服,而且这样也更容易避免与其他 Angular 来源发生冲突。您可以随时更改命名空间。由于您没有创建新的 $scope
实例,因此它在性能上也有点“轻”,但我不确定是否有很多收获。
为了实现隐私,我建议将您的数据封装在服务或工厂中。请记住,控制器并不总是单例;视图和控制器之间存在 1:1 关系,您可以多次实例化同一个控制器!然而,工厂和服务对象是单例。他们非常擅长存储共享数据。
让所有控制器从单例中获取状态的副本,并确保所有控制器都使用 Service/Factory 上定义的行为修改单例状态。
function modalController(dataItemsService) {
var vm = this;
vm.selectedItems = dataItemsService.SelectedItems(); // get a copy of my data
vm.updateItem = dataItemService.UpdateItem; // update the source
}
等等,我怎么知道我的应用程序的另一部分何时更改了我的私人数据?我如何知道何时获取 SelectedItems 的新副本?这就是 $scope.$watch 发挥作用的地方:
function modalController(dataItemsService, $scope) {
var vm = this;
vm.updateItem = dataItemService.UpdateItem; // update the source
// periodically check the selectedItems and get a fresh copy.
$scope.$watch(dataItemsService.SelectedItems, function(items) {
vm.items = items;
});
// thanks $scope!
}
如果您的数据不共享,或者如果您的私有数据代表视图层而不是模型层,那么将其保留在控制器中是完全可以的。
function Controller() {
var buttonClicked = false;
this.click = function() {
buttonClicked = true; // User can not lie and say they didn't.
};
}
最后,不要像您的参考那样在您的控制器中使用 JQUERY!
$("#existConfirmDialog").modal('hide');
这个例子可能不是纯粹的邪恶,但要避免在指令之外访问和修改 DOM,你不想通过修改它下面的 DOM 来破坏应用程序的其他部分.
关于构建 Angular 代码和 JavaScript 使用变量绑定与私有方法命名函数约定时的行为的几个问题。在 AngularJS 中通过私有方法命名使用变量绑定函数/第一个 class 函数是否有性能或风格原因?提升在每种方法中是如何受到影响的?下面的第二种方法会减少执行的提升量吗?这会对应用程序性能产生显着影响吗?
一个私有方法命名的例子。这是构造 Angular 代码的推荐方法吗?
(function () {
'use strict'
function modalController(dataItemsService, $scope) {
var vm = this;
function _getSelectedItems() {
return dataItemsService.SelectedItems();
}
function _deleteSelectedItems() {
dataItemService.DeleteItem();
$("#existConfirmDialog").modal('hide');
}
vm.SelectedItems = _getSelectedItems;
vm.deleteItemRecord = _deleteItemRecord;
}
angular.module('app').controller('modalController', ['dataItemService', '$scope', modalController]
})();
变量绑定函数的一个例子。这种在控制器中构建 angular 代码的方法怎么样 - 在 performance/style 方面有什么缺点或优点吗?
angular.module('appname').controller("NameCtrl", ["$scope", "$log", "$window", "$http", "$timeout", "SomeService",
function ($scope, $log, $window, $http, $timeout, TabService) {
//your controller code
$scope.tab = 0;
$scope.changeTab = function(newTab){
$scope.tab = newTab;
};
$scope.isActiveTab = function(tab){
return $scope.tab === tab;
};
}
]);
第一种方法使用“私有”方法并通过 public 别名公开它们,称为 Revealing Module Pattern,尽管在示例中这些方法实际上并不是私有的。
后者是一个相当标准的 Constructor Pattern,使用 $scope 作为上下文。
Is there a performance or stylistic reason for using
variable
bound functions / first class functions in AngularJS over private method naming?Is [there] a recommended way to structure Angular code?
TL;DR
从根本上来说,这两种风格并没有太大区别 多于。一个使用
$scope
,另一个使用this
。一个构造函数定义在闭包中,一个定义在行内。有些情况下您可能需要私有方法或值。 还有风格和(可能微不足道的)表现 在
$scope
上使用变量this
/vm
的原因。这些并不相互排斥。您可能想要使用 基本的,基本的,老派的构造函数模式,以及很多 人们通过
公开状态和行为this
而不是$scope
.您可以在 Controller 中允许自己的数据隐私,但大多数 Service/Factory 应该利用这个时间。主要的例外是代表视图状态的数据。
请不要在您的控制器中使用 jQuery。
参考文献:
AngularJS Style Guide 托德座右铭。
要彻底回答您的问题,我认为了解 Controller 的职责很重要。每个控制器的工作是向视图公开一组严格的状态和行为。简而言之,只分配给 this
或 $scope
您不介意用户在您的视图中看到或玩的东西。
问题中的 variable
(vm
, $scope
) 是由 Controller 函数创建的实例的上下文 (this
)。
$scope
是Angular的“特殊”语境;它已经定义了一些行为供您使用(例如 $scope.$watch)。 $scopes
也遵循继承链,即 $scope 继承分配给其父 $scope 的状态和行为。
拿这两个控制器:
angular.module("Module")
.controller("Controller", ["$scope", function($scope) {
$scope.tab = 0;
$scope.incrementTab = function() {
$scope.tab++;
};
}])
.controller("OtherController", ["$scope", function($scope) {
// nothing
}]);
还有风景
<div ng-controller="Controller">
<p>{{ tab }}</p>
<button ng-click="incrementTab();">Increment</button>
<div ng-controller="OtherController">
<p>{{ tab }}</p>
<button ng-click="incrementTab();">Increment</button>
</div>
</div>
示例here
你会注意到,即使我们没有在 OtherController 中定义 $scope.tab
,它也从 Controller 继承了它,因为 Controller 是它在 DOM 中的父级。在显示选项卡的两个地方,您应该看到“0”。这可能是您所指的 "hoisting",尽管那是一个完全不同的概念。
单击第一个按钮时会发生什么?在我们暴露“制表符”的两个地方,它们现在将显示“1”。当您按下第二个按钮时,两者也会更新和递增。
当然,我很可能不希望我的子选项卡与父选项卡具有相同的选项卡值。如果将 OtherController 更改为:
.controller("OtherController", ["$scope", function($scope) {
$scope.tab = 42;
}]);
您会注意到此行为已发生变化 - 选项卡的值不再同步。
但现在很混乱:我有两个叫做“制表符”的东西是不一样的。其他人可能稍后使用“tab”写了一些代码并无意中破坏了我的代码。
我们过去常常通过在 $scope
上使用命名空间来解决这个问题,例如$scope.vm
并将所有内容分配给命名空间:$scope.vm.tab = 0;
<div ng-controller="OtherController">
<p>{{ vm.tab }}</p>
<button ng-click="vm.incrementTab();">Increment</button>
</div>
另一种方法是使用 this
的简单性和简洁性,并利用 controllerAs 语法。
.controller("OtherController", function() {
this.tab = 0;
});
<div ng-controller="OtherController as oc">
<p>{{ oc.tab }}</p>
</div>
对于习惯使用普通 JS 的人来说,这可能会更舒服,而且这样也更容易避免与其他 Angular 来源发生冲突。您可以随时更改命名空间。由于您没有创建新的 $scope
实例,因此它在性能上也有点“轻”,但我不确定是否有很多收获。
为了实现隐私,我建议将您的数据封装在服务或工厂中。请记住,控制器并不总是单例;视图和控制器之间存在 1:1 关系,您可以多次实例化同一个控制器!然而,工厂和服务对象是单例。他们非常擅长存储共享数据。
让所有控制器从单例中获取状态的副本,并确保所有控制器都使用 Service/Factory 上定义的行为修改单例状态。
function modalController(dataItemsService) {
var vm = this;
vm.selectedItems = dataItemsService.SelectedItems(); // get a copy of my data
vm.updateItem = dataItemService.UpdateItem; // update the source
}
等等,我怎么知道我的应用程序的另一部分何时更改了我的私人数据?我如何知道何时获取 SelectedItems 的新副本?这就是 $scope.$watch 发挥作用的地方:
function modalController(dataItemsService, $scope) {
var vm = this;
vm.updateItem = dataItemService.UpdateItem; // update the source
// periodically check the selectedItems and get a fresh copy.
$scope.$watch(dataItemsService.SelectedItems, function(items) {
vm.items = items;
});
// thanks $scope!
}
如果您的数据不共享,或者如果您的私有数据代表视图层而不是模型层,那么将其保留在控制器中是完全可以的。
function Controller() {
var buttonClicked = false;
this.click = function() {
buttonClicked = true; // User can not lie and say they didn't.
};
}
最后,不要像您的参考那样在您的控制器中使用 JQUERY!
$("#existConfirmDialog").modal('hide');
这个例子可能不是纯粹的邪恶,但要避免在指令之外访问和修改 DOM,你不想通过修改它下面的 DOM 来破坏应用程序的其他部分.