为什么angularjs上下文仅继承第一级对象

时间:2013-09-20 00:03:49

标签: javascript angularjs inheritance scoping

如果下面任何输入的改变将导致所有输入的改变。 据我所知,这是因为数据对象对于所有3个范围都是通用的

<div class="content-container" ng-app="">
<input type="text" ng-model="data.message">
<h1>{{data.message}}</h1>
<div ng-controller="FirstController">
    <input type="text" ng-model="data.message">
    <h1>{{data.message}}</h1>
</div>
<div ng-controller="SecondController">
    <input type="text" ng-model="data.message">
    <h1>{{data.message}}</h1>
</div>

但是如果下面的每个范围都有它自己的消息对象:

<div class="content-container" ng-app="">
<input type="text" ng-model="message">
<h1>{{message}}</h1>
<div ng-controller="FirstController">
    <input type="text" ng-model="message">
    <h1>{{message}}</h1>
</div>
<div ng-controller="SecondController">
    <input type="text" ng-model="message">
    <h1>{{message}}</h1>
</div>

我不清楚为什么angular为每个范围创建“message”对象但不为每个范围创建“data”对象?这两个例子之间的主要区别是什么?

1 个答案:

答案 0 :(得分:2)

这不是关于AngularJS的工作原理 - 它实际上是关于JavaScript如何工作的。请考虑以下事项:

function Parent() { 
  this.message = ''; 
  this.data    = {};
}
function Child() {}; Child.prototype = new Parent();

如您所见,Parent在用作构造函数时,为新对象定义了两个属性。假设我们将使用第一个存储基元,第二个存储对象。

Child函数定义非常简单:没有自己的属性,在其原型链中有Parent个对象。现在,他们正在做更多的事情:

var c = new Child();
c.message      = '42';
c.data.message = '42';
console.log(c.hasOwnProperty('message'));         // true
console.log(c.hasOwnProperty('data'));            // false
console.log(c.data.hasOwnProperty('message'));    // true

看到区别?在第一种情况下,使用c.message,我们在对象(c)本身上定义了一个新属性 - 现在该属性隐藏了在其上定义的同名属性它的原型。

然而,在第二种情况下,我们仍然使用 parent 的属性,使用新属性扩展其值。 c上没有定义新属性,只有其原型受到影响;差异在这里更有说服力:

var d = new Child();
d.message      = '34';
d.data.message = '34';

console.log(c.message);      // still '42'
console.log(c.data.message); // now '34'

使用Angular指令时会发生类似的事情:定义了一个新的作用域,从其父作用域继承了所有“模型”属性。但除非这些属性是“两级”,否则分配给它们将在子级别引入同名属性,并为父级定义一个属性。

我建议从Angular wiki学习Understanding Scopes文档:它对此行为有更多实质性(并且也有丰富的说明!)解释。然而,这句话很好地总结了它:

  

通过遵循以下内容,可以轻松避免使用原语这个问题   “最佳实践”总是有'。'在您的ng模型中。

对于一个确实只想使用原语的情况,它提到了一些解决方法:{I}我认为$parent.parentScopeProperty是最直接的。