sessionStorage/localStorage scope

Firstly, localStorage and sessionStorage are 2 objects on the window object. They tie to the origin of the current window.

As a result they are bind to :

  1. protocol, http/https are different
  2. domain
    1. subdomain can share with parent by manually setting document.domain.
    2. cannot share with
  3. port

Same thing apply to 302 redirect. The session/local storage value set on a page is not available on the page after redirect as long as they are different origin, even if they are in the SAME tab/window.

It can also be understood as per application based, as their values can be viewed in the dev-tool’s Application Tab.



MDN link


ng-show ng-if not just in DOM or not

I was thinking I had enough knowledge about the different about ng-if and ng-show which are one adds/removes the containing stuff from the DOM and the latter one just use CSS to hide/show. What’s ironic is I even sometimes use this as an interview question. Today I was bitten by it.

According to the Angualrjs Doc:

The ngIf directive removes or recreates a portion of the DOM tree based on an {expression}. If the expression assigned to ngIf evaluates to a false value then the element is removed from the DOM, otherwise a clone of the element is reinserted into the DOM.


No problem.

However in the smaller part, there is another important message:

Note that when an element is removed using ngIf its scope is destroyed and a new scope is created when the element is restored. The scope created within ngIf inherits from its parent scope using prototypal inheritance. An important implication of this is if ngModel is used within ngIf to bind to a javascript primitive defined in the parent scope. In this case any modifications made to the variable within the child scope will override (hide) the value in the parent scope.

So ng-if actually uses ‘transclude’, to create a child scope of the parent.

So if you have something like:

 <input type="text" />

and use $scope.myInput in the controller, it is fine. However after you wrap it with ng-if:

<div ng-if="someCondition">
  <input ng-model="myInput" /></div>

your $scope.myInput would not work anymore since now the myInput is in the child scope and based on the prototypical inheritance mechanism in js, you wont be able to get it from child.

solution 1 would be using ng-show so that it is still in the parent scope.

solution2 could be using $parent.myInput as ng-model

solution 3 is to use ‘controller as vm‘ syntax (angualrjs 1.3 onwards) where the ng-model becomes vm.myInput, so when child scope is trying to bind it, it first try to create $watch the myInput on vm object in its own scope, and after not found, it goes up to the parent scope which is the controller scope which is the one we want.

One article about Regular transclusion and element transclusion.


angularjs $scope form undefined

Was developing some form with angular, things work perfect until I add a angular-ui bootstrap tab to enclose 2 different form in each tab.

when i try to access the form with $scope.formName, the formName is undefined.

It turns out that the angularUI tab directive uses transclude which will create a child scope to the parent which here is the controller $scope as the sibling of the directive scope. Then the formName can only be access by the new child scope.

One solution is define a var in the controller scope like $scope.forms = {};

Then for the form name in the transclude directive, we use forms.formName1. This way we could still access it from our controller by just call $scope.forms.formName1.

This works because the inheritance mechanism in JS is prototype chain. So when child scope tries to create the forms.formName1, it first tries to find the forms object in its own scope which definitely does not have it since it is created on the fly. Then it will try to find it from the parent(up to the prototype chain) and since we have it defined in the controller scope, it uses this ‘forms’ object we created to define the variable formName1. As a result we could still use it in the controller like $scope.forms.formName1.$valild to do our stuff.

Javascript 严格模式详解 use strict

全局变量显式声明(must use var)


“use strict”;

v = 1; // 报错,v未声明

for(i = 0; i < 2; i++) { // 报错,i未声明


重名错误(No duplicate var/function name)




  ”use strict”;

var o = {
p: 1,
p: 2
}; // 语法错误



  ”use strict”;

function f(a, a, b) { // 语法错误

return ;


保留字(reserved keywords)

为了向将来Javascript的新版本过渡,严格模式新增了一些保留字:implements, interface, let, package, private, protected, public, static, yield。


  function package(protected) { // 语法错误

“use strict”;

var implements; // 语法错误





  ”use strict”;

var x = 2;“var x = 5; x”)); // 5; // 2

inspect angularjs scope controller in chrome(webkit)

Pick an element in the HTML panel of the developer tools and type this in the console


In webkit $0 is a reference to the selected DOM node in the elements tab, so by doing this you get the selected DOM node scope printed out in the console

Also you could assign this to a var for future reference like
var scope = angular.element($0).scope();

Then you could do, scope.yourModelName to check values.

$0-$4 stand for the 5 DOM nodes that you recently selected. $5 will be undefined.


There are some very useful Chrome Extensions that you might want to checkout:

  • Batarang. This has been around for a while.
  • ng-inspector. This is the newest one, and as the name suggests, it allows you to inspect your application’s scopes.

angularjs scope inheritence primitive object

JavaScript Prototypal Inheritance

It is important to first have a solid understanding of JavaScript prototypal inheritance, especially if you are coming from a server-side background and you are more familiar with classical inheritance. So let’s review that first.

Suppose parentScope has properties aString, aNumber, anArray, anObject, and aFunction. If childScope prototypically inherits from parentScope, we have:

normal prototypal inheritance

(Note that to save space, I show the anArray object as a single blue object with its three values, rather than an single blue object with three separate gray literals.)

If we try to access a property defined on the parentScope from the child scope, JavaScript will first look in the child scope, not find the property, then look in the inherited scope, and find the property. (If it didn’t find the property in the parentScope, it would continue up the prototype chain… all the way up to the root scope). So, these are all true:

childScope.aString === 'parent string'
childScope.anArray[1] === 20
childScope.anObject.property1 === 'parent prop1'
childScope.aFunction() === 'parent output'

Suppose we then do this:

childScope.aString = 'child string'

The prototype chain is not consulted, and a new aString property is added to the childScope. This new property hides/shadows the parentScope property with the same name. This will become very important when we discuss ng-repeat and ng-include below.


Suppose we then do this:

childScope.anArray[1] = '22'
childScope.anObject.property1 = 'child prop1'

The prototype chain is consulted because the objects (anArray and anObject) are not found in the childScope. The objects are found in the parentScope, and the property values are updated on the original objects. No new properties are added to the childScope; no new objects are created. (Note that in JavaScript arrays and functions are also objects.)

follow the chain

Suppose we then do this:

childScope.anArray = [100, 555]
childScope.anObject = { name: 'Mark', country: 'USA' }

The prototype chain is not consulted, and child scope gets two new object properties that hide/shadow the parentScope object properties with the same names.

not following the chain


  • If we read childScope.propertyX, and childScope has propertyX, then the prototype chain is not consulted.
  • If we set childScope.propertyX, the prototype chain is not consulted.

One last scenario:

delete childScope.anArray
childScope.anArray[1] === 22  // true

We deleted the childScope property first, then when we try to access the property again, the prototype chain is consulted.

after deleting a property

Here is a jsfiddle where you can see the above javascript prototypical inheritance examples being modified and their result (open up your browser’s console to see the output. The console output can be viewed as what the ‘RootScope’ would see).

Angular Scope Inheritance

The contenders:

  • The following create new scopes, and inherit prototypically: ng-repeat, ng-include, ng-switch, ng-view, ng-controller, directive with scope: true, directive with transclude: true.
  • The following creates a new scope which does not inherit prototypically: directive withscope: { ... }. This creates an “isolate” scope instead.

Note, by default, directives do not create new scope — i.e., the default is scope: false.


Suppose we have in our controller:

$scope.myPrimitive = 50;
$scope.myObject    = {aNumber: 11};

And in our HTML:

<script type="text/ng-template" id="/tpl1.html">
    <input ng-model="myPrimitive">
<div ng-include src="'/tpl1.html'"></div>

<script type="text/ng-template" id="/tpl2.html">
    <input ng-model="myObject.aNumber">
<div ng-include src="'/tpl2.html'"></div>

Each ng-include generates a new child scope, which prototypically inherits from the parent scope.


Typing (say, “77”) into the first input textbox causes the child scope to get a new myPrimitive scope property that hides/shadows the parent scope property of the same name. This is probably not what you want/expect.

ng-include primitive

Typing (say, “99”) into the second input textbox does not result in a new child property. Because tpl2.html binds the model to an object property, prototypal inheritance kicks in when the ngModel looks for object myObject — it finds it in the parent scope.

ng-include object

We can rewrite the first template to use $parent, if we don’t want to change our model from a primitive to an object:

<input ng-model="$parent.myPrimitive">

Typing (say, “22”) into this input textbox does not result in a new child property. The model is now bound to a property of the parent scope (because $parent is a child scope property that references the parent scope).

ng-include $parent

For all scopes (prototypal or not), Angular always tracks a parent-child relationship (i.e., a hierarchy), via scope properties $parent, $$childHead and $$childTail. I normally don’t show these scope properties in the diagrams.

For scenarios where form elements are not involved, another solution is to define a function on the parent scope to modify the primitive. Then ensure the child always calls this function, which will be available to the child scope due to prototypal inheritance. E.g.,

// in the parent scope
$scope.setMyPrimitive = function(value) {
    $scope.myPrimitive = value;

Here is a sample fiddle that uses this “parent function” approach. (This was part of a Stack Overflow post.)

See also and


ng-switch scope inheritance works just like ng-include. So if you need 2-way data binding to a primitive in the parent scope, use $parent, or change the model to be an object and then bind to a property of that object. This will avoid child scope hiding/shadowing of parent scope properties.

See also AngularJS, bind scope of a switch-case?


Ng-repeat works a little differently. Suppose we have in our controller:

$scope.myArrayOfPrimitives = [ 11, 22 ];
$scope.myArrayOfObjects    = [{num: 101}, {num: 202}]

And in our HTML:

<ul><li ng-repeat="num in myArrayOfPrimitives">
       <input ng-model="num"></input>
<ul><li ng-repeat="obj in myArrayOfObjects">
       <input ng-model="obj.num"></input>

For each item/iteration, ng-repeat creates a new scope, which prototypically inherits from the parent scope, but it also assigns the item’s value to a new property on the new child scope. (The name of the new property is the loop variable’s name.) Here’s what the Angular source code for ng-repeat actually is:

childScope = scope.$new(); // child scope prototypically inherits from parent scope ...     
childScope[valueIdent] = value; // creates a new childScope property

If item is a primitive (as in myArrayOfPrimitives), essentially a copy of the value is assigned to the new child scope property. Changing the child scope property’s value (i.e., using ng-model, hence child scope property num) does not change the array the parent scope references. So in the first ng-repeat above, each child scope gets a num property that is independent of the myArrayOfPrimitives array:

ng-repeat primitive

This ng-repeat will not work (like you want/expect it to). In Angular 1.0.2 or earlier, typing into the textboxes changes the values in the gray boxes, which are only visible in the child scopes. In Angular 1.0.3+, typing into the text boxes has no effect. (See Artem’s explanation as to why on StackOverflow.) What we want is for the inputs to affect the myArrayOfPrimitives array, not a child scope primitive property. To accomplish this, we need to change the model to be an array of objects.

So, if item is an object, a reference to the original object (not a copy) is assigned to the new child scope property. Changing the child scope property’s value (i.e., using ng-model, hence obj.num) does change the object the parent scope references. So in the second ng-repeat above, we have:

ng-repeat object

(I colored one line gray just so that it is clear where it is going.)

This works as expected. Typing into the textboxes changes the values in the gray boxes, which are visible to both the child and parent scopes.

See also Difficulty with ng-model, ng-repeat, and inputs and
ng-repeat and databinding


TBD, but I think it acts just like ng-include.


Nesting controllers using ng-controller results in normal prototypal inheritance, just like ng-include and ng-switch, so the same techniques apply. However, “it is considered bad form for two controllers to share information via $scope inheritance” — A service should be used to share data between controllers instead.

(If you really want to share data via controllers scope inheritance, there is nothing you need to do. The child scope will have access to all of the parent scope properties. See also Controller load order differs when loading or navigating)


  1. default (scope: false) – the directive does not create a new scope, so there is no inheritance here. This is easy, but also dangerous because, e.g., a directive might think it is creating a new property on the scope, when in fact it is clobbering an existing property. This is not a good choice for writing directives that are intended as reusable components.
  2. scope: true – the directive creates a new child scope that prototypically inherits from the parent scope. If more than one directive (on the same DOM element) requests a new scope, only one new child scope is created. Since we have “normal” prototypal inheritance, this is like ng-include and ng-switch, so be wary of 2-way data binding to parent scope primitives, and child scope hiding/shadowing of parent scope properties.
  3. scope: { ... } – the directive creates a new isolate/isolated scope. It does not prototypically inherit. This is usually your best choice when creating reusable components, since the directive cannot accidentally read or modify the parent scope. However, such directives often need access to a few parent scope properties. The object hash is used to set up two-way binding (using ‘=’) or one-way binding (using ‘@’) between the parent scope and the isolate scope. There is also ‘&’ to bind to parent scope expressions. So, these all create local scope properties that are derived from the parent scope. Note that attributes are used to help set up the binding — you can’t just reference parent scope property names in the object hash, you have to use an attribute. E.g., this won’t work if you want to bind to parent property parentProp in the isolated scope: <div my-directive> and scope: { localProp: '@parentProp' }. An attribute must be used to specify each parent property that the directive wants to bind to: <div my-directive the-Parent-Prop=parentProp> and scope: { localProp: '@theParentProp' }.
    Isolate scope’s __proto__ references a Scope object. Isolate scope’s $parent references the parent scope, so although it is isolated and doesn’t inherit prototypically from the parent scope, it is still a child scope.
    For the picture below we have
    <my-directive interpolated="{{parentProp1}}" twowayBinding="parentProp2"> and
    scope: { interpolatedProp: '@interpolated', twowayBindingProp: '=twowayBinding' }
    Also, assume the directive does this in its linking function: scope.someIsolateProp = "I'm isolated"
    isolate scope
    One final note: use attrs.$observe('attr_name', function(value) { ... }) in the linking function to get the interpolated value of isolate scope properties that use the ‘@’ notation. E.g., if we have this in the linking function —attrs.$observe('interpolated', function(value) { ... })value would be set to 11. (scope.interpolatedProp is undefined in the linking function. In contrast,scope.twowayBindingProp is defined in the linking function, since it uses the ‘=’ notation.)
    For more information on isolate scopes see
  4. transclude: true – the directive creates a new “transcluded” child scope, which prototypically inherits from the parent scope. So if your transcluded content (i.e., the stuff that ng-transclude will be replaced with) requires 2-way data binding to a primitive in the parent scope, use $parent, or change the model to be an object and then bind to a property of that object. This will avoid child scope hiding/shadowing of parent scope properties.
    The transcluded and the isolated scope (if any) are siblings — the $parent property of each scope references the same parent scope. When a transcluded and an isolate scope both exist, isolate scope property $$nextSibling will reference the transcluded scope.
    For more information on transcluded scopes, see AngularJS two way binding not working in directive with transcluded scope
    For the picture below, assume the same directive as above with this addition:transclude: true
    transcluded scope

This fiddle has a showScope() function that can be used to examine an isolate scope and its associated transcluded scope. See the instructions in the comments in the fiddle.


There are four types of scopes:

  1. normal prototypal scope inheritance — ng-include, ng-switch, ng-controller, directive with scope: true
  2. normal prototypal scope inheritance with a copy/assignment — ng-repeat. Each iteration of ng-repeat creates a new child scope, and that new child scope always gets a new property.
  3. isolate scope — directive with scope: {...}. This one is not prototypal, but ‘=’, ‘@’, and ‘&’ provide a mechanism to access parent scope properties, via attributes.
  4. transcluded scope — directive with transclude: true. This one is also normal prototypal scope inheritance, but it is also a sibling of any isolate scope.

For all scopes (prototypal or not), Angular always tracks a parent-child relationship (i.e., a hierarchy), via properties $parent and $$childHead and $$childTail.

Diagrams were generated with GraphViz “*.dot” files, which are on github. Tim Caswell’s“Learning JavaScript with Object Graphs” was the inspiration for using GraphViz for the diagrams.

The above was originally posted on StackOverflow.

Angular’s $scope event system $emit, $broadcast and $on

Angular’s $emit, $broadcast and $on fall under the common “publish/subscribe” design pattern, or can do, in which you’d publish an event and subscribe/unsubscribe to it somewhere else. The Angular event system is brilliant, it makes things flawless and easy to do (as you’d expect!) but the concept behind it isn’t so simple to master and you can often be left wondering why things don’t work as you thought they might.

For those who are new to Angular and haven’t used or seen $emit, $broadcast or $on, let’s clarify what they do before we look at $scope and $rootScope event and scope relationships and how to utilise the event system correctly – as well as understand what’s really going on.

$scope.$emit up, $scope.$broadcast down

Using $scope.$emit will fire an event up the $scope. Using $scope.$broadcast will fire an event downthe $scope. Using $scope.$on is how we listen for these events. A quick example:


// firing an event upwards
$scope.$emit('myCustomEvent', 'Data to send');

// firing an event downwards
$scope.$broadcast('myCustomEvent', {
  someProp: 'Sending you an Object!' // send whatever you want

// listen for the event in the relevant $scope
$scope.$on('myCustomEvent', function (event, data) {
  console.log(data); // 'Data to send'