我试图在UI-Booststrap modal之上创建一个小的抽象层来删除重复的代码,工厂允许你像这样调用模态
modal.dialog({
templateUrl: <String>
scope: <Scope>
}). then(...);
我在我的工厂设置验证
if (settings && angular.isString(settings.templateUrl) ...)
但是当我试图验证<Scope>
部分时,我运气不好。我找不到angular.isScope
函数。
我该如何测试呢?
我知道,通过大量的工作,任何对象看起来都像$scope
对象,如果你是偏执狂并尝试添加更多验证规则就像走下兔洞一样,你最终会丢失所以请不要这样做。我想要的是一种简单的方法,可以检测到相当数量的错误值来设置我的验证。
答案 0 :(得分:3)
我开始查看角度代码。我找到了isScope函数来执行此操作
function isScope(obj) {
return obj && obj.$evalAsync && obj.$watch;
}
基本上duck-typing检查对象是否类似于角度范围。这很简单,可用于大多数情况,但我想知道是否有更好的方法,比
更可靠isScope({$watch:true ,$evalAsync:true}) => true
我发现每个范围对象都包含一个指向$root
的{{1}}属性。这对于$rootScope
本身也是有效的。
$rootScope
所以这仍然是鸭子打字,但比前一个好一点,因为我们使用identity来检查对象是否完全相同。将其移至可用的工厂
$rootScope.$root === $rootScope => true
angular.module('app', [])
.factory('isScope', function($rootScope) {
return function(obj) {
return obj && obj.$watch && obj.$evalAsync && obj.$root === $rootScope;
};
});
angular.module('app', [])
.factory('isScope', function($rootScope) {
return function(obj) {
return obj && obj.$watch && obj.$evalAsync && obj.$root === $rootScope;
};
})
.controller('TestController', function($scope, isScope) {
$scope.resultObject = isScope({
$watch: true,
$evalAsync: true
});
$scope.resultScope = isScope($scope);
});
当然这很容易被<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="TestController">
<div>Object: {{resultObject}}</div>
<div>Scope: {{resultScope}}</div>
</div>
所愚弄,但在测试简单对象时会更好。
但是,我一直在寻找和阅读源代码,并发现所有范围都是使用名为Scope的函数语句创建的(显然是:P)。当然这个功能是私密的,不会暴露给外面的世界,或者是它!! ???
想象一下,当我看到它时,我感到惊讶
这对创建新的作用域当然没用,有$rootScope.$new
的api函数,但可以用于使用原型链测试作用域。
好的但等等,我知道孤立的范围没有原型地从其他范围继承,因此链将被破坏。事实证明,对于那些情况,角度使用new Scope()
来实例化一个全新的隔离范围,因此这个技巧可能仍然有效,并且它会比以前的尝试更好。
{..., $root: $rootScope}
这将检测我们之前的尝试
function isScope(obj) {
var Scope = $rootScope.constructor;
return obj instanceof Scope;
}
将其移至可用工厂
console.log(isScope({..., $root: $rootScope})); => false
angular.module('app', [])
.factory('isScope', function($rootScope) {
return function(obj) {
return obj instanceof $rootScope.constructor;
};
});
angular.module('app', [])
.factory('isScope', function($rootScope) {
return function(obj) {
return obj instanceof $rootScope.constructor;
};
})
.controller('TestController', function($rootScope, $scope, isScope) {
$scope.objectResult = isScope({
$evalAsync: true,
$watch: true,
$root: $rootScope
});
$scope.scopeResult = isScope($scope);
});
就像我说的,这不是失败证明,实际上很容易使用像
这样的东西<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="TestController">
<div>
Object: {{objectResult}}
</div>
<div>
Scope: {{scopeResult}}
</div>
</div>
但足以测试大多数实际用例。当然,像instanceof的每次使用一样,在多个上下文(例如帧或窗口)中使用时会产生不良副作用,而且对于不同帧中的实际范围对象,这也会返回false,但这是一个非常极端的情况。不太可能发生。
答案 1 :(得分:1)
您可以检查对象是否是$ scope的实例。这不是完美的,但它可能就足够了。
if(scope instanceof $scope.constructor){
/* enter code here */
}