Javascript检查对象属性是否存在,即使对象未定义

Javascript检查对象属性是否存在,即使对象未定义,javascript,oop,underscore.js,Javascript,Oop,Underscore.js,我想检查对象是否存在,是否有属性。目前,我得到一个“myObject未定义”错误,停止检查 即使myObject可能不存在,如何使以下内容仍能正常工作 if (myObject.myProperty) { ... } else { ... } 我甚至试图检查对象/变量是否存在,但得到一个错误: if(foo){console.log('hello');}给出错误未捕获引用错误:未定义foo。这是一个JSFIDLE您可以使用“短路”&&操作符: if (myObject &&am

我想检查对象是否存在,是否有属性。目前,我得到一个“myObject未定义”错误,停止检查

即使myObject可能不存在,如何使以下内容仍能正常工作

if (myObject.myProperty) {
  ...
} else {
  ...
}
我甚至试图检查对象/变量是否存在,但得到一个错误:

if(foo){console.log('hello');}
给出错误未捕获引用错误:未定义foo。这是一个JSFIDLE

您可以使用“短路”
&&
操作符:

if (myObject && myObject.myProperty) { 
    ...
}
如果
myObject
为“falsey”(例如未定义),
&
操作符将不会费心尝试计算右侧表达式,从而避免尝试引用不存在对象的属性

变量
myObject
必须已经声明了课程,上面的测试是为了测试它是否已经被指定了一个定义值。

尝试:

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

如果
myObject
存在并且还具有
myproperty
,则此代码进入
if
块的主体。如果由于某种原因,
myObject
不存在,
和&
会短路,并且不会计算
myObject.myProperty

我很惊讶在基本Javascipt接口中找不到这个有用的函数

下面是我在项目中经常使用的辅助函数。它检查最终链元素的值是否可以访问,并且没有错误“无法获取未定义的”。这样使用它:

getChained(this, "this.path.to.some.object.someFunction().result");

/**
 * 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;
  }
}
getChained(这是“this.path.to.some.object.someFunction().result”);
/**
*解构链,检查是否所有其他元素都未定义。
*可以在链中使用数组和函数,甚至可以传递参数
*在他们里面。
*
*唯一的限制是不允许使用带点的字符串值。
*
*@param{Object}chainScope起始对象,链范围。
*保证不被未定义。
*必需参数。
*@param{String}从没有第一个对象的代码链生成链
*没有第一个点。
*必需参数。
*@param{Array}
*函数参数链中函数的参数。
*数组中的对象与顺序相对应
*链中函数的定义。每件物品
*包含其函数的参数。
*对象语法迫使我们创建参数
*名称,即使只有它的值。
*@返回{Object | | String | | Number | | | Boolean | | | undefined}最终链元素值或undefined,如果任何其他链元素返回undefined。
*/
getChained:函数(
链镜,
链条
函数(参数表){
var部件;
var部分;
var partIndex;
var目标=未定义;
var函数指数=0;
如果(
chainScope==未定义||
chainScope==null){
回报目标;
}
target=chainScope;//链的起始范围。
parts=getParts();
//用数值替换计算零件的继电器链
//对于函数调用和数组:
为了(
partIndex=0;
partIndex<零件长度;
partIndex++){
如果(目标===未定义){
//链元素未定义,链本身也未定义:
返回未定义;
}
零件=零件[零件索引];
如果(
部分索引(“”>
部分索引(“\”)&&
部分索引(“”>
第.indexOf部分(“\”){
//这是一个函数:
target=getFunctionValue();
函数索引++;
继续;
}
如果(
部分索引(“[”)>
部分索引(“\”)&&
部分索引(“]”>
第.indexOf部分(“\”){
//它是数组的元素:
target=getArrayValue();
继续;
}
如果(
零件类型==“字符串”&&
目标!==null&&
目标!==未定义){
//它是一个物体:
目标=目标[部分];
继续;
}
}
回报目标;
/**
*拆分字符串。分隔符是括号外的点。
*括号内的点没有拆分。
*/
函数getParts(){
var分隔符=“.”;
var OPEN_CHARS=[
"(",
"[",
"\"",
"\'"
];
变量关闭字符=[
")",
"]",
"\"",
"\'"
];
var SUB_SEPARATOR_OPEN=“[”;
var SUB_SEPARATOR_CLOSE=“]”;
返回(
分路器(
分路器(
),;
/**
*通过链根分离器进行拆分。
*开始字符和结束字符之间没有拆分。
*
*@param{String}Chain用于分析字符。
*@返回已拆分的{Array}链元素。
*/
函数拆分器(链字符串){
变量部分=[
];
var=0;
var-char1;
var指数;
var提取物;
var cutFromIndex=0;
var链阵列;
//字符串到数组并附加结束点
//要使用通用规则进行拆分,请执行以下操作:
链式阵列=
(链字符串+“)。
拆分(“”);
为了(
链指数=0;
chainIndex0){
//这是一个开放的括号:
开放++;
继续;
}
if(关闭字符索引of(字符1)>0){
//这是一个结束括号:
打开--;
继续;
}
如果(打开===0){
//括号外的字符:
if(char1==分隔符){
//它是一个点-在它成为元素之前的一切:
提取=
链式数组.slice(
cutFromIndex,
chainIndex)。//剪切一个元素。
将(“”;//数组连接到字符串。
零件。推(
提取物);
if (myObject?.myProperty) { ... }
if (myObject && myObject.myProperty) { ... }