Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does the Javascript expression 'a = a || function() {...}' mean?

I'm not sure what this construct means but I've seen it a few times. The example below is from another Stack Overflow question. I'm not sure how to interpret the initial "or" construct itself:

Object.keys = Object.keys || (function () {
  var hasOwnProperty = Object.prototype.hasOwnProperty,
      hasDontEnumBug = !{toString:null}.propertyIsEnumerable("toString"),
      DontEnums = [ 
          'toString', 'toLocaleString', 'valueOf', 'hasOwnProperty',
          'isPrototypeOf', 'propertyIsEnumerable', 'constructor'
      ],
      DontEnumsLength = DontEnums.length;
  //etc...
});
like image 851
Vangoe Avatar asked Aug 15 '11 18:08

Vangoe


People also ask

What is named function expression?

Named functions can be either declared in a statement or used in an expression. Named function expressions create readable stack traces. The name of the function is bound inside its body, and that can be useful. And we can use the name to have a function invoke itself, or to access its properties like any other object.

What does || do in JavaScript?

The logical OR ( || ) operator (logical disjunction) for a set of operands is true if and only if one or more of its operands is true. It is typically used with boolean (logical) values. When it is, it returns a Boolean value.

How do you write an expression in JavaScript?

The assignment expression y = x = f() starts to evaluate. The y on this assignment's left-hand side evaluates into a reference to the variable named y . The assignment expression x = f() starts to evaluate. The x on this assignment's left-hand side evaluates into a reference to the variable named x .


1 Answers

a = a || function(){...} is an idiom that is very common in Javascript. It relies on two concepts that, while not unique to Javascript, you might not yet be familiar with.

1. Operator short circuiting

Operator short circuiting[wikipedia] is a compiler optimization that was invented to prevent unnecessary evaluation.

To demonstrate this, let us suppose that we want to determine whether a person is a teenager: that is, whether a person has an age inclusively between 13 and 19 years.

var isTeenager = person.age >= 13 && person.age <= 19;

Now, let us suppose that the code executes and it turns out that the person is younger than 13. The first condition will be evaluated and will return false. Since the program now knows that the the left hand side of the && operator is false, and since && requires both sides to be true in order to evaluate to true, it knows that evaluating the right hand side is pointless.

In other words, the program, having seen that the person's age is not greater than 13, already knows that he is not a teenager and couldn't care less whether or not he is less than 19.

The same sort of principle applies to the || operator. Suppose we wanted to know if a person can ride the bus for free: that is, if the person is over 70 years old or is handicapped.

var canRideFree = person.age >= 70 || isHandicapped(person);

If the person is over 70, the program already knows that he can ride free. At this point, the program does not care if he is handicapped or not and thus does not evaluate the call to the isHandicapped function. If, on the other hand, the person was younger than 70, then canRideFree would be set to whatever isHandicapped returns.

2. Truthy and falsy values

Truthy and falsy values[some random person's blog] are the boolean evaluations of objects. In Javascript, every object will evaluate to either a "truthy" or a "falsy" value.

An expression is "falsy" if its value is any of these:

false, null, undefined, 0, "", NaN

Everything else is truthy.

People take advantage of the fact that a null or undefined variable evaluates to false. This means that you can check if a variable exists very easily:

if (a) { /* a exists and is not a falsy value */ }

Combining what we know

The || operator short circuits and returns the value of the last expression that it evaluates. This principle combines with truthiness in this single statement:

Object.keys = Object.keys || function() {...}

If Object.keys is truthy, it will be evaluated and assigned to itself. Otherwise, Object.keys will be assigned to the function. This is a very common idiom in Javascript for checking if a value already exists and assigning it to something else if it doesn't.

Some other languages, such as C#, that do not have truthiness, have a null-coalescing operator[MSDN] that has a similar purpose.

object Value = PossiblyNullValue ?? ValueIfNull;

In this code, Value will be assigned to PossiblyNullValue, unless it's null, in which case it will be assigned to ValueIfNull.

tl;dr [wikipedia]

If you didn't bother to read anything I said above, all you need to know is that a = a || function() {...} basically does what this code does:

if (exists(Object.keys)) {
  Object.keys = Object.keys;
} else { 
  Object.keys = function() {...};
}

function exists(obj) {
  return typeof obj !== "undefined" && 
         obj !== null && 
         obj !== false &&
         obj !== 0 &&
         obj !== "" &&
         !isNaN(obj);
}
like image 113
13 revs Avatar answered Oct 12 '22 16:10

13 revs