简体   繁体   中英

What those two lines mean: o[x] = o[x] || {}; o = o[x];

This is the code I get, but I don't know this two lines means:

o[arr[i]] = o[arr[i]] || {};
o = o[arr[i]]; 

Full code:

var GLOBAL={};
GLOBAL.namespace=function(str){
    var arr = str.split("."), o=GLOBAL;

    for(i=(arr[0]=="GLOBAL") ? 1 : 0; i<arr.length; i++){
        o[arr[i]] = o[arr[i]] || {};
        o = o[arr[i]];
    }
};

GLOBAL.namespace("A.Dog");
// GLOBAL.A = {};
// GLOBAL.A.Dog = {};
GLOBAL.A.Dog.name = "diudiu";
alert(GLOBAL.A.Dog.name)

There are two statements:

This:

o[arr[i]] = o[arr[i]] || {};

And:

 o = o[arr[i]];

The second sets the nested object o to its key arr[i] , overwriting itself with one of it's own key/values.

The first set's the o object's key arr[i] to itself or an empty object. The || operator is a boolean or and will only trigger the {} if o[arr[i]] evaluates to false.

This kind of statement is often used to intialize a variable (eg in the global namespace) when you don't know if it's already been initialized (so you don't overwrite it).

Break it down step-by-step to make is clearer:

o[arr[i]] = o[arr[i]] || {};

is the same as:

var x = arr[i];
o[x] = o[x] || {};

is the same as:

var x = arr[i];
if (o[x] == undefined) {
  o[x] = {};
}

The pattern A = B || DEFAULT_VALUE A = B || DEFAULT_VALUE is an idiom which uses the short-circuiting nature of the || operator. In javascript, the || operator does not return true or false but instead it returns the first non-false value or false . So if the first variable is not falsy it evaluates to the value of the first variable otherwise it evaluates to the value of the second variable.

The first line ensures that o[arr[i]] is defined. It either sets o[arr[i]] to itself if it was previously created, or a new object (ie {} ) if o[arr[i]] is undefined.

The second line assigns the object from the first line to o so that the namespace traversal can continue.

The function GLOBAL.namespace(str) is used to create a namespace (and its sub-namespaces) if it doesn't already exist.

Here is how it works:

  • It splits up str by periods into sub-namespaces:
    arr = str.split(".")

  • It sets o to the global namespace:
    o=GLOBAL

  • It skips the first sub-namespace if the first sub-namespace is GLOBAL :
    (arr[0]=="GLOBAL") ? 1 : 0

For each sub-namespace in arr :

  • It checks if it exists under o , and if it doesn't, it creates it:
    o[arr[i]] = o[arr[i]] || {};

  • It sets up o to work one level deeper, so it can work on the next sub-namespace:
    o = o[arr[i]];

For purposes of understanding the function, here's a version with the purpose of each variable spelled out, and steps split up a bit more:

var GLOBAL={};
GLOBAL.namespace=function(fullNamespaceName){
  var namespaceNames = fullNamespaceName.split("."); // arr
  var currentNamespace=GLOBAL; // o
  var currentIndex = (namespaceNames[0]=="GLOBAL") ? 1 : 0; // i

  for(; currentIndex<namespaces.length; currentIndex++){
    var subNamespaceName = namespaceNames[currentIndex];
    var subNamespace = currentNamespace[subNamespaceName];
    subNamespace = subNamespace || {};
    currentNamespace[subNamespaceName] = subNamespace;
    currentNamespace = subNamespace;
  }
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM