7.2 Testing and Comparison Operations

7.2.1 RequireObjectCoercible ( argument )

The abstract operation RequireObjectCoercible takes argument argument. It throws an error if argument is a value that cannot be converted to an Object using ToObject. It is defined by Table 19:

Table 19: RequireObjectCoercible Results
Argument Type Result
Undefined Throw a TypeError exception.
Null Throw a TypeError exception.
Boolean Return argument.
Number Return argument.
String Return argument.
Symbol Return argument.
BigInt Return argument.
Object Return argument.

7.2.2 IsArray ( argument )

The abstract operation IsArray takes argument argument. It performs the following steps when called:

  1. If Type(argument) is not Object, return false.
  2. If argument is an Array exotic object, return true.
  3. If argument is a Proxy exotic object, then
    1. If argument.[[ProxyHandler]] is null, throw a TypeError exception.
    2. Let target be argument.[[ProxyTarget]].
    3. Return ? IsArray(target).
  4. Return false.

7.2.3 IsCallable ( argument )

The abstract operation IsCallable takes argument argument (an ECMAScript language value). It determines if argument is a callable function with a [[Call]] internal method. It performs the following steps when called:

  1. If Type(argument) is not Object, return false.
  2. If argument has a [[Call]] internal method, return true.
  3. Return false.

7.2.4 IsConstructor ( argument )

The abstract operation IsConstructor takes argument argument (an ECMAScript language value). It determines if argument is a function object with a [[Construct]] internal method. It performs the following steps when called:

  1. If Type(argument) is not Object, return false.
  2. If argument has a [[Construct]] internal method, return true.
  3. Return false.

7.2.5 IsExtensible ( O )

The abstract operation IsExtensible takes argument O (an Object). It returns a completion record which, if its [[Type]] is normal, has a [[Value]] which is a Boolean. It is used to determine whether additional properties can be added to O. It performs the following steps when called:

  1. Return ? O.[[IsExtensible]]().

7.2.6 IsIntegralNumber ( argument )

The abstract operation IsIntegralNumber takes argument argument. It determines if argument is a finite integral Number value. It performs the following steps when called:

  1. If Type(argument) is not Number, return false.
  2. If argument is NaN, +∞𝔽, or -∞𝔽, return false.
  3. If floor(abs((argument))) ≠ abs((argument)), return false.
  4. Return true.

7.2.7 IsPropertyKey ( argument )

The abstract operation IsPropertyKey takes argument argument (an ECMAScript language value). It determines if argument is a value that may be used as a property key. It performs the following steps when called:

  1. If Type(argument) is String, return true.
  2. If Type(argument) is Symbol, return true.
  3. Return false.

7.2.8 IsRegExp ( argument )

The abstract operation IsRegExp takes argument argument. It performs the following steps when called:

  1. If Type(argument) is not Object, return false.
  2. Let matcher be ? Get(argument, @@match).
  3. If matcher is not undefined, return ! ToBoolean(matcher).
  4. If argument has a [[RegExpMatcher]] internal slot, return true.
  5. Return false.

7.2.9 IsStringPrefix ( p, q )

The abstract operation IsStringPrefix takes arguments p (a String) and q (a String). It determines if p is a prefix of q. It performs the following steps when called:

  1. If q can be the string-concatenation of p and some other String r, return true. Otherwise, return false.
Note

Any String is a prefix of itself, because r may be the empty String.

7.2.10 SameValue ( x, y )

The abstract operation SameValue takes arguments x (an ECMAScript language value) and y (an ECMAScript language value). It returns a completion record whose [[Type]] is normal and whose [[Value]] is a Boolean indicating whether or not the two arguments are the same value. It performs the following steps when called:

  1. If Type(x) is different from Type(y), return false.
  2. If Type(x) is Number or BigInt, then
    1. Return ! Type(x)::sameValue(x, y).
  3. Return ! SameValueNonNumeric(x, y).
Note

This algorithm differs from the IsStrictlyEqual Algorithm by treating all NaN values as equivalent and by differentiating +0𝔽 from -0𝔽.

7.2.11 SameValueZero ( x, y )

The abstract operation SameValueZero takes arguments x (an ECMAScript language value) and y (an ECMAScript language value). It returns a completion record whose [[Type]] is normal and whose [[Value]] is a Boolean indicating whether or not the two arguments are the same value (ignoring the difference between +0𝔽 and -0𝔽). It performs the following steps when called:

  1. If Type(x) is different from Type(y), return false.
  2. If Type(x) is Number or BigInt, then
    1. Return ! Type(x)::sameValueZero(x, y).
  3. Return ! SameValueNonNumeric(x, y).
Note

SameValueZero differs from SameValue only in that it treats +0𝔽 and -0𝔽 as equivalent.

7.2.12 SameValueNonNumeric ( x, y )

The abstract operation SameValueNonNumeric takes arguments x (an ECMAScript language value, but not a Number or a BigInt) and y (an ECMAScript language value, but not a Number or a BigInt). It returns a completion record whose [[Type]] is normal and whose [[Value]] is a Boolean. It performs the following steps when called:

  1. Assert: Type(x) is the same as Type(y).
  2. If Type(x) is Undefined, return true.
  3. If Type(x) is Null, return true.
  4. If Type(x) is String, then
    1. If x and y are exactly the same sequence of code units (same length and same code units at corresponding indices), return true; otherwise, return false.
  5. If Type(x) is Boolean, then
    1. If x and y are both true or both false, return true; otherwise, return false.
  6. If Type(x) is Symbol, then
    1. If x and y are both the same Symbol value, return true; otherwise, return false.
  7. If x and y are the same Object value, return true. Otherwise, return false.

7.2.13 IsLessThan ( x, y, LeftFirst )

The abstract operation IsLessThan takes arguments x (an ECMAScript language value), y (an ECMAScript language value), and LeftFirst (a Boolean). It provides the semantics for the comparison x < y, returning true, false, or undefined (which indicates that at least one operand is NaN). The LeftFirst flag is used to control the order in which operations with potentially visible side-effects are performed upon x and y. It is necessary because ECMAScript specifies left to right evaluation of expressions. If LeftFirst is true, the x parameter corresponds to an expression that occurs to the left of the y parameter's corresponding expression. If LeftFirst is false, the reverse is the case and operations must be performed upon y before x. It performs the following steps when called:

  1. If the LeftFirst flag is true, then
    1. Let px be ? ToPrimitive(x, number).
    2. Let py be ? ToPrimitive(y, number).
  2. Else,
    1. NOTE: The order of evaluation needs to be reversed to preserve left to right evaluation.
    2. Let py be ? ToPrimitive(y, number).
    3. Let px be ? ToPrimitive(x, number).
  3. If Type(px) is String and Type(py) is String, then
    1. If IsStringPrefix(py, px) is true, return false.
    2. If IsStringPrefix(px, py) is true, return true.
    3. Let k be the smallest non-negative integer such that the code unit at index k within px is different from the code unit at index k within py. (There must be such a k, for neither String is a prefix of the other.)
    4. Let m be the integer that is the numeric value of the code unit at index k within px.
    5. Let n be the integer that is the numeric value of the code unit at index k within py.
    6. If m < n, return true. Otherwise, return false.
  4. Else,
    1. If Type(px) is BigInt and Type(py) is String, then
      1. Let ny be ! StringToBigInt(py).
      2. If ny is NaN, return undefined.
      3. Return BigInt::lessThan(px, ny).
    2. If Type(px) is String and Type(py) is BigInt, then
      1. Let nx be ! StringToBigInt(px).
      2. If nx is NaN, return undefined.
      3. Return BigInt::lessThan(nx, py).
    3. NOTE: Because px and py are primitive values, evaluation order is not important.
    4. Let nx be ? ToNumeric(px).
    5. Let ny be ? ToNumeric(py).
    6. If Type(nx) is the same as Type(ny), return Type(nx)::lessThan(nx, ny).
    7. Assert: Type(nx) is BigInt and Type(ny) is Number, or Type(nx) is Number and Type(ny) is BigInt.
    8. If nx or ny is NaN, return undefined.
    9. If nx is -∞𝔽 or ny is +∞𝔽, return true.
    10. If nx is +∞𝔽 or ny is -∞𝔽, return false.
    11. If (nx) < (ny), return true; otherwise return false.
Note 1

Step 3 differs from step 2.c in the algorithm that handles the addition operator + (13.15.3) by using the logical-and operation instead of the logical-or operation.

Note 2

The comparison of Strings uses a simple lexicographic ordering on sequences of code unit values. There is no attempt to use the more complex, semantically oriented definitions of character or string equality and collating order defined in the Unicode specification. Therefore String values that are canonically equal according to the Unicode standard could test as unequal. In effect this algorithm assumes that both Strings are already in normalized form. Also, note that for strings containing supplementary characters, lexicographic ordering on sequences of UTF-16 code unit values differs from that on sequences of code point values.

7.2.14 IsLooselyEqual ( x, y )

The abstract operation IsLooselyEqual takes arguments x (an ECMAScript language value) and y (an ECMAScript language value). It provides the semantics for the comparison x == y, returning true or false. It performs the following steps when called:

  1. If Type(x) is the same as Type(y), then
    1. Return IsStrictlyEqual(x, y).
  2. If x is null and y is undefined, return true.
  3. If x is undefined and y is null, return true.
  4. NOTE: This step is replaced in section B.3.6.2.
  5. If Type(x) is Number and Type(y) is String, return IsLooselyEqual(x, ! ToNumber(y)).
  6. If Type(x) is String and Type(y) is Number, return IsLooselyEqual(! ToNumber(x), y).
  7. If Type(x) is BigInt and Type(y) is String, then
    1. Let n be ! StringToBigInt(y).
    2. If n is NaN, return false.
    3. Return IsLooselyEqual(x, n).
  8. If Type(x) is String and Type(y) is BigInt, return IsLooselyEqual(y, x).
  9. If Type(x) is Boolean, return IsLooselyEqual(! ToNumber(x), y).
  10. If Type(y) is Boolean, return IsLooselyEqual(x, ! ToNumber(y)).
  11. If Type(x) is either String, Number, BigInt, or Symbol and Type(y) is Object, return IsLooselyEqual(x, ? ToPrimitive(y)).
  12. If Type(x) is Object and Type(y) is either String, Number, BigInt, or Symbol, return IsLooselyEqual(? ToPrimitive(x), y).
  13. If Type(x) is BigInt and Type(y) is Number, or if Type(x) is Number and Type(y) is BigInt, then
    1. If x or y are any of NaN, +∞𝔽, or -∞𝔽, return false.
    2. If (x) = (y), return true; otherwise return false.
  14. Return false.

7.2.15 IsStrictlyEqual ( x, y )

The abstract operation IsStrictlyEqual takes arguments x (an ECMAScript language value) and y (an ECMAScript language value). It provides the semantics for the comparison x === y, returning true or false. It performs the following steps when called:

  1. If Type(x) is different from Type(y), return false.
  2. If Type(x) is Number or BigInt, then
    1. Return ! Type(x)::equal(x, y).
  3. Return ! SameValueNonNumeric(x, y).
Note

This algorithm differs from the SameValue Algorithm in its treatment of signed zeroes and NaNs.