Javascript check if object property exists, even w

2019-01-15 20:56发布

I want to check if an object exists, and has a property. Currently I get a "myObject is undefined" error that stops the check.

How can I make the following still work correctly even when myObject may not exist?

if (myObject.myProperty) {
  ...
} else {
  ...
}

I am trying to just even check if a object / variable exists but getting an error:

if (foo) { console.log('hello'); } gives the error Uncaught ReferenceError: foo is not defined. Here is a jsfiddle http://jsfiddle.net/cfUss/

3条回答
smile是对你的礼貌
2楼-- · 2019-01-15 21:03

I've been suprised not to find this helpful function in basic Javascipt interface. Below is a helper function I often use in my projects. It checks if the value of the final chain element is reachable without an error "can't get ... of undefined":

/**
 * Deconstructs a chain, checking if every other element is undefined. 
 * You can use arrays and functions in chain and even pass parameters
 * inside them.
 *
 * The only limitation is no string values with dots are allowed.
 *
 * @param {Object} chainScope Starting object, the chain scope.
 *                            Guaranteed not to be be undefined.
 *                            Required parameter.
 * @param {String} chain A chain from code without first object 
 *                       and without first dot.
 *                       Required parameter.
 * @param {Array<Array<Object||String||Number||Boolean||undefined>>}
 *        functionsParameters Parameters for functions in chain.
 *                            Object in the array correspond the order
 *                            of functions in chain. Every object
 *                            contains parameters for its function.
 *                            Object syntax forces us to create parameter 
 *                            names even if you only have its value.
 * @returns {Object||String||Number||Boolean||undefined} Final chain element value or undefined, if any other chain element returned undefined.
 */
getChained: function (
  chainScope,
  chain,
  functionsParameters) {

  var parts;
  var part;
  var partIndex;
  var target = undefined;
  var functionIndex = 0;

  if (
    chainScope === undefined ||
    chainScope === null) {

    return target;
  }

  target = chainScope; // The starting scope of a chain.

  parts = getParts();

  // Relay chain substituting calculated parts with values
  // for function calls and arrays:
  for (
    partIndex = 0;
    partIndex < parts.length;
    partIndex++) {

    if (target === undefined) {
      // Chain element is undefined and so is the chain itself:
      return undefined;
    }

    part = parts[partIndex];

    if (
      part.indexOf("(") >
      part.indexOf("\"") &&
      part.indexOf("(") >
      part.indexOf("\'")) {

      // It's a function:

      target = getFunctionValue();
      functionIndex++;
      continue;
    }

    if (
      part.indexOf("[") >
      part.indexOf("\"") &&
      part.indexOf("]") >
      part.indexOf("\'")) {

      // It's an array's element:

      target = getArrayValue();
      continue;
    }

    if (
      typeof part === "string" &&
      target !== null &&
      target !== undefined) {

      // It's an object:

      target = target[part];
      continue;
    }
  }

  return target;

  /**
   * Splits string. Separators are dots outside the brackets.
   * No splitting for dots inside the brackets.
   */
  function getParts() {

    var SEPARATOR = ".";
    var OPEN_CHARS = [
      "(",
      "[",
      "\"",
      "\'"
    ];
    var CLOSE_CHARS = [
      ")",
      "]",
      "\"",
      "\'"
    ];
    var SUB_SEPARATOR_OPEN = "[";
    var SUB_SEPARATOR_CLOSE = "]";

    return(
      splitBySubSeparator(
        splitBySeparator(
          chain)));

    /**
     * Split by chain root separator.
     * No splitting between opening and closing characters.
     *
     * @param {String} chainString Chain to analyse characters.
     * @returns {Array<String>} Chain elements splitted.
     */
    function splitBySeparator(chainString) {
      var parts = [
      ];
      var opened = 0;
      var char1;
      var chainIndex;
      var extract;
      var cutFromIndex = 0;
      var chainArray;

      // String to array and attach the ending dot 
      // to be able to split using common rule:
      chainArray =
        (chainString + ".").
        split("");

      for (
        chainIndex = 0;
        chainIndex < chainArray.length;
        chainIndex++) {

        char1 = chainArray[chainIndex];

        if (OPEN_CHARS.indexOf(char1) > 0) {
          // It's an opening bracket:
          opened++;
          continue;
        }

        if (CLOSE_CHARS.indexOf(char1) > 0) {
          // It's a closing bracket:
          opened--;
          continue;
        }

        if (opened === 0) {
          // It's character outside the brackets:
          if (char1 === SEPARATOR) {

            // It's a dot - everything before it is an element:

            extract =
              chainArray.slice(
                cutFromIndex,
                chainIndex). // Cut an element.
              join(""); // Array to String.

            parts.push(
              extract);

            cutFromIndex = chainIndex + 1; // Shift to escape a dot.
          } else {
            // It's an ordinary character:
            continue;
          }
        }
      }

      return parts;
    }

    /**
     * Splits by root subobject or array elements calls.
     * Subcalls are searched inside the splitted chain elements.
     * (now separator is "[" instead of ".").
     * Can split several consequently called subobjects
     * without a need to deconstruct enclosures.
     * Second iteration finds array elements and object subcalls
     * inside resulting elements (now separator is "[" instead of "."):
     */
    function splitBySubSeparator(parts) {
      var newParts = [
      ];
      var opened = 0;
      var char1;
      var partIndex;
      var chainIndex;
      var chainArray;

      for (
        partIndex = 0;
        partIndex < parts.length;
        partIndex++) {

        var part = parts[partIndex];

        chainArray = part.split("");

        for (
          chainIndex = 0;
          chainIndex < chainArray.length;
          chainIndex++) {

          char1 = chainArray[chainIndex];

          if (
            opened === 0 &&
            char1 === SUB_SEPARATOR_OPEN) {

            // Start of subcall for an array element or object:
            part =
              part.substr(0, chainIndex) +
              SEPARATOR +
              part.substr(chainIndex + 1);

            opened++;
          }

          if (
            opened > 0 &&
            char1 === SUB_SEPARATOR_CLOSE) {

            // End of subcall for an array element or object:
            part =
              part.substr(0, chainIndex) +
              "" +
              part.substr(chainIndex + 1);

            opened--;
          }
        }

        // Split changed element by separators again and 
        // relay into a cumulative array:
        newParts =
          newParts.concat(
            splitBySeparator(part));
      }

      return newParts;
    }
  }

  /**
   * Creates and returns method call result. Puts required
   * parameters into method.
   *
   * @returns {Object||String||Number||Boolean||undefined} Method execution result.
   */
  function getFunctionValue() {
    var value;
    var name;

    name =
      part.
      split("(")[0];

    if (functionsParameters) {
      value =
        target[name].
        apply(
          target,
          functionsParameters[
            functionIndex
          ]);
    } else {
      value =
        target[name].
        apply(
          target);
    }

    return value;
  }

  /**
   * Returns array element.
   *
   * @returns {Object||String||Number||Boolean||undefined} Value of array element.
   */
  function getArrayValue() {
    var value;
    var arrayName;
    var itemName;

    arrayName =
      part.
      split("[")[0];

    itemName =
      (part.
        split("[")[1].
        split("]")[0]).
      split("\'").
      join("").
      split("\"").
      join("");

    if (target[arrayName]) {
      value =
        target[arrayName][itemName];
    }

    return value;
  }
}
查看更多
女痞
3楼-- · 2019-01-15 21:08

Try:

if(myObject && myObject.myProperty){ ... }

This code enters the body of the if block if myObject exists and also has myproperty. If myObject doesn't exist for some reason, the && short-circuits and does not evaluated myObject.myProperty.

查看更多
我想做一个坏孩纸
4楼-- · 2019-01-15 21:14

You can use the "short circuit" && operator:

if (myObject && myObject.myProperty) { 
    ...
}

If myObject is "falsey" (e.g. undefined) the && operator won't bother trying to evaluate the right-hand expression, thereby avoiding the attempt to reference a property of a non-existent object.

The variable myObject must have course already have been declared, the test above is for whether it has been assigned a defined value.

查看更多
登录 后发表回答