Javascript检查对象属性是否存在,即使对象未定义
我想检查对象是否存在,是否有属性。目前,我得到一个“myObject未定义”错误,停止检查 即使myObject可能不存在,如何使以下内容仍能正常工作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
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) { ... }