“ API参考范围”页面显示:
范围可以从父范围继承。
该开发者指南范围页说:
范围(典型地)从其父范围继承属性。
子作用域通常是从其父作用域继承的,但并非总是如此。该规则的一个例外是带有的指令scope: { ... }
-这会创建一个“隔离”作用域,该作用域不会原型继承。创建“可重用组件”指令时,经常使用此构造。
对于细微差别,作用域继承通常是直截了当的……直到你需要在子作用域中进行2路数据绑定(即表单元素,ng-model)。如果你尝试从子作用域内部绑定到父作用域中的原语(例如,数字,字符串,布尔值),则Ng-repeat,ng-switch和ng-include可能会使你绊倒。它不能像大多数人期望的那样工作。子作用域具有其自己的属性,该属性隐藏/阴影相同名称的父属性。你的解决方法是
通过遵循始终具有“’ ”的“最佳实践”,可以很容易避免原语的此问题。在你的ng模型中 –观看3分钟值得。Misko用演示了原始绑定问题ng-switch。
有一个 ‘。’ 在你的模型中,将确保原型继承在起作用。所以用
<input type="text" ng-model="someObj.prop1">
<!--rather than
<input type="text" ng-model="prop1">`
-->
JavaScript原型继承
也放在AngularJS Wiki上: https : //github.com/angular/angular.js/wiki/Understanding-Scopes
首先,必须对原型继承有深刻的了解,特别是如果你来自服务器端背景并且对类继承有更深的了解时,这一点很重要。因此,让我们先回顾一下。
假设parentScope具有属性aString,aNumber,anArray,anObject和aFunction。如果childScope原型继承自parentScope,则我们具有:
原型继承
(请注意,为了节省空间,我将anArray
对象显示为具有三个值的单个蓝色对象,而不是将其显示为具有三个单独的灰色文字的单个蓝色对象。)
如果我们尝试从子作用域访问在parentScope上定义的属性,JavaScript将首先在子作用域中查找,而不是查找该属性,然后在继承的作用域中查找并找到该属性。(如果未在parentScope中找到该属性,它将沿原型链继续前进,一直到根作用域为止)。因此,这些都是对的:
childScope.aString === 'parent string'
childScope.anArray[1] === 20
childScope.anObject.property1 === 'parent prop1'
childScope.aFunction() === 'parent output'
假设我们然后这样做:
childScope.aString = 'child string'
未查询原型链,并且将新的aString属性添加到childScope。 此新属性将隐藏/阴影具有相同名称的parentScope属性。 当我们在下面讨论ng-repeat和ng-include时,这将变得非常重要。
假设我们然后这样做:
childScope.anArray[1] = '22'
childScope.anObject.property1 = 'child prop1'
之所以查询原型链,是因为在childScope中找不到对象(anArray和anObject)。这些对象在parentScope中找到,并且属性值在原始对象上更新。没有向childScope添加任何新属性;没有创建新对象。(请注意,在JavaScript中,数组和函数也是对象。)
假设我们然后这样做:
childScope.anArray = [100, 555]
childScope.anObject = { name: 'Mark', country: 'USA' }
不查询原型链,子作用域将获得两个新的对象属性,这些属性将隐藏/阴影具有相同名称的parentScope对象属性。
Takeaways:
delete childScope.anArray
childScope.anArray[1] === 22 // true
我们首先删除了childScope属性,然后当我们再次尝试访问该属性时,将查询原型链。
角范围继承
竞争者:
ng-include
假设我们在控制器中:
$scope.myPrimitive = 50;
$scope.myObject = {aNumber: 11};
在我们的HTML中:
<script type="text/ng-template" id="/tpl1.html">
<input ng-model="myPrimitive">
</script>
<div ng-include src="'/tpl1.html'"></div>
<script type="text/ng-template" id="/tpl2.html">
<input ng-model="myObject.aNumber">
</script>
<div ng-include src="'/tpl2.html'"></div>
每个ng-include都会生成一个新的子作用域,该子作用域通常从父作用域继承。
在第一个输入文本框中键入(例如“ 77”)会导致子范围获得一个新的myPrimitive范围属性,该属性将隐藏/阴影相同名称的父范围属性。这可能不是你想要/期望的。
在第二个输入文本框中键入(例如,“ 99”)不会导致新的子属性。因为tpl2.html将模型绑定到对象属性,所以当ngModel查找对象myObject时,原型继承就开始了-它在父作用域中找到它。
如果我们不想将模型从基本类型更改为对象,则可以重写第一个模板以使用$ parent:
<input ng-model="$parent.myPrimitive">
在此输入文本框中键入(例如“ 22”)不会产生新的子属性。现在,模型已绑定到父作用域的属性(因为$ parent是引用父作用域的子作用域属性)。
对于所有范围(无论是否是原型),Angular始终通过范围属性$ parent,$ childchildHead和$$ childTail跟踪父子关系(即层次结构)。我通常不会在图中显示这些范围属性。
对于不涉及表单元素的方案,另一种解决方案是在父作用域上定义一个函数来修改基元。然后确保子级始终调用此函数,由于原型继承,该函数将可用于子级作用域。例如,
// in the parent scope
$scope.setMyPrimitive = function(value) {
$scope.myPrimitive = value;
}
ng-开关
ng-switch作用域继承的工作方式与ng-include一样。因此,如果你需要与父作用域中的原语进行双向数据绑定,请使用$ parent或将模型更改为对象,然后绑定至该对象的属性。这将避免子范围隐藏/隐藏父范围属性。
另请参阅AngularJS,绑定开关盒的范围?
ng-repeat
Ng-repeat的工作方式略有不同。假设我们在控制器中:
$scope.myArrayOfPrimitives = [ 11, 22 ];
$scope.myArrayOfObjects = [{num: 101}, {num: 202}]
在我们的HTML中:
<ul><li ng-repeat="num in myArrayOfPrimitives">
<input ng-model="num">
</li>
<ul>
<ul><li ng-repeat="obj in myArrayOfObjects">
<input ng-model="obj.num">
</li>
<ul>
对于每个项目/迭代,ng-repeat都会创建一个新的范围,该范围通常是从父范围继承的,但也会将该项目的值分配给新的子范围上的新属性。(新属性的名称是循环变量的名称。)以下是ng-repeat的Angular源代码:
childScope = scope.$new(); // child scope prototypically inherits from parent scope
...
childScope[valueIdent] = value; // creates a new childScope property
如果item是基元(例如,在myArrayOfPrimitives中),则实质上将值的副本分配给新的子作用域属性。更改子作用域属性的值(即使用NG-模型,因此子范围num
)并不会改变阵列父范围引用。因此,在上面的第一个ng-repeat中,每个子范围都获得一个num
独立于myArrayOfPrimitives数组的属性:
此ng-repeat将不起作用(就像你想要/期望的那样)。在文本框中键入将更改灰色框中的值,这些值仅在子作用域中可见。我们想要的是使输入影响myArrayOfPrimitives数组,而不是子作用域原始属性。为此,我们需要将模型更改为对象数组。
因此,如果item是对象,则将对原始对象(不是副本)的引用分配给新的子范围属性。更改子范围属性的值(即使用ng-model obj.num
)确实会更改父范围引用的对象。因此,在上面的第二个ng-repeat中,我们有:
(我只将一行涂成灰色,以便清楚地知道行进路线。)
这按预期工作。键入文本框会更改灰色框中的值,这对子作用域和父作用域都是可见的。
ng控制器
使用ng-controller嵌套控制器会导致正常的原型继承,就像ng-include和ng-switch一样,因此适用相同的技术。但是,“两个控制器通过$ scope继承共享信息被认为是错误的形式” -http://onehungrymind.com/angularjs-sticky-notes-pt-1-architecture/ 应该使用服务来在两个之间共享数据控制器代替。
(如果你确实想通过Controller作用域继承共享数据,则无需执行任何操作。子作用域将有权访问所有父作用域属性。另请参见加载或导航时Controller的加载顺序有所不同)
指令
1. default(scope: false)
-该指令不会创建新的作用域,因此此处没有继承。这很容易,但也很危险,因为,例如,一条指令可能认为它正在作用域上创建新属性,而实际上却在破坏现有属性。对于编写旨在用作可重用组件的指令,这不是一个好的选择。
2. scope: true-
伪指令创建了一个新的子范围,该子范围从原型上继承自父范围。如果一个以上的指令(在同一DOM元素上)请求一个新范围,则仅创建一个新的子范围。由于我们具有“常规”原型继承,因此就像ng-include和ng-switch一样,因此请谨慎使用2路数据绑定到父作用域原语,以及子作用域隐藏/遮蔽父作用域属性。
3. scope: { ... }
-该指令创建一个新的隔离/隔离范围。它不是原型继承的。在创建可重用组件时,这通常是最佳选择,因为该指令不会意外读取或修改父作用域。但是,此类指令通常需要访问一些父范围属性。对象哈希用于在父作用域和隔离作用域之间建立双向绑定(使用’=’)或单向绑定(使用’@’)。还有“&”绑定到父作用域表达式。因此,所有这些都创建了从父范围派生的本地范围属性。请注意,属性用于帮助设置绑定-你不能仅在对象哈希中引用父作用域属性名称,而必须使用属性。例如,如果你要绑定到父属性,则此方法将无效parentProp
在隔离范围内:<div my-directive>
和scope: { localProp: ‘@parentProp’ }。必须使用属性来指定指令要绑定到的每个父属性:<div my-directive the-Parent-Prop=parentProp>
和scope: { localProp: '@theParentProp' }
。
隔离范围的__proto__
引用对象。隔离作用域的$ parent引用父作用域,因此,尽管它是隔离的并且不从父作用域原型继承,但它仍然是子作用域。
对于下面的图片中,我们有
<my-directive interpolated="{{parentProp1}}" twowayBinding="parentProp2">和 scope: { interpolatedProp: '@interpolated', twowayBindingProp: '=twowayBinding' }
同样,假设该指令执行此操作在其链接功能:scope.someIsolateProp = "I'm isolated"
transclude: true
该小提琴具有一项showScope()
功能,可用于检查隔离和超越的示波器。请参阅小提琴中注释中的说明。
摘要
范围有四种类型:
scope: true
scope: {...}
。这不是原型,但是'=','@'
和'&'
提供了一种通过属性访问父范围属性的机制。在编程中,我们经常会想获取并扩展一些东西。 例如,我们有一个 user 对象及其属性和方法,并希望将 admin 和 guest 作为基于 user 稍加修改的变体。我们想重用 user 中的内容,而不是复制/重新实现它的方法,而只是在其之上构建一个新的对象。 原型继承(Prototypal inheritance) 这个语言特性能够帮助我们实现这一需求。 [[Prototype]] 在 Java
在传统的基于Class的语言如Java、C++中,继承的本质是扩展一个已有的Class,并生成新的Subclass。 由于这类语言严格区分类和实例,继承实际上是类型的扩展。但是,JavaScript由于采用原型继承,我们无法直接扩展一个Class,因为根本不存在Class这种类型。 但是办法还是有的。我们先回顾Student构造函数: function Student(props) { t
“(原型)继承” 我们已经看到了一些近似的“类”机制黑进 JavaScript 程序。但是如果我们没有一种近似的“继承”,JavaScript 的“类”将会更空洞。 实际上,我们已经看到了一个常被称为“原型继承”的机制如何工作:a 可以“继承自” Foo.prototype,并因此可以访问 myName() 函数。但是我们传统的想法认为“继承”是两个“类”间的关系,而非“类”与“实例”的关系。 回
问题内容: 在父控制器作用域中,我已定义将其设置为“ x”。然后在子范围中,我使用ngModel 进行了定义: 加载页面后,会按预期正确设置为“ x”。当我选择“ y”时,在CtrlB中$ scope会按预期给出“ y”。 但是,当我检查的范围(使用AngularJS的batarang),它给“X”。 jsFiddle:http : //jsfiddle.net/sudhh/GGKjp/2/ 预览
本文向大家介绍JavaScript原型继承和原型链原理详解,包括了JavaScript原型继承和原型链原理详解的使用技巧和注意事项,需要的朋友参考一下 这篇文章主要介绍了JavaScript原型继承和原型链原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 在讨论原型继承之前,先回顾一下关于创建自定义类型的方式,这里推荐将构造函数和原型模式组
问题内容: 我是JavaScript OOP的新手。您能否解释以下代码块之间的区别?我测试了两个模块。什么是最佳做法,为什么? 第一块: 第二块: 为什么笔者添加和使用方法,并没有宣布他们的内部方法类和在类? 为什么需要重新设置为?是当覆盖的属性设置?我注释了这一行,没有任何改变。 为什么叫在构造函数?当我这样做时,不会被“继承”的属性和方法 问题答案: 这两个块的不同之处在于,在第一个示例中该实