在PHP中,你可以这样做if(isset($array['foo'])){…}。在JavaScript中,你经常使用if(array.foo){…}来做同样的事情,但这不是完全相同的语句。条件也将计算为false if数组。Foo确实存在,但为false或0(也可能为其他值)。

JavaScript中与PHP的isset完美对应的是什么?

从更广泛的意义上说,一个关于JavaScript如何处理不存在的变量、没有值的变量等的通用的、完整的指南会很方便。


更新:11年零11个月前,我发布了这个问题,哇,它仍然有很多活动。现在,我非常确定,当我写这篇文章时,我只是想知道如何检查关联数组(也就是字典)中属性的存在,因此(对我来说)正确的答案涉及hasOwnProperty或in操作符。我对检查局部或全局变量不感兴趣。

但是,虽然我记得很清楚,但在写的问题中,这种意图并不十分清楚,甚至与之直接矛盾!我还没提到关联数组,PHP的isset也有其他功能。让这成为我们所有人的一个教训,让我们知道在一个问题中正确地陈述你的要求是多么重要,以及全局变量、局部变量、对象属性、字典键和其他什么东西是多么重要。

与此同时,很多很多人也提供了这个问题的答案,所以对于那些通过谷歌找到这个问题的人来说,我很高兴我的含糊在某种程度上有所帮助。不管怎样,我只是想澄清一下。


当前回答

function isset(variable) {
    try {
        return typeof eval(variable) !== 'undefined';
    } catch (err) {
        return false;
    }
}

其他回答

旧线程,但有新的方法来运行等效的isset()。

ESNext(2019年12月第四阶段)

两种新的语法允许我们极大地简化isset()函数的使用:

可选的链接(?)。 空合并运算符(??)

请仔细阅读文档并注意浏览器兼容性。

回答

请看下面的解释。注意我使用的是StandardJS语法

示例使用

// IMPORTANT pass a function to our isset() that returns the value we're
// trying to test(ES6 arrow function)
isset(() => some) // false

// Defining objects
let some = { nested: { value: 'hello' } }

// More tests that never throw an error
isset(() => some) // true
isset(() => some.nested) // true
isset(() => some.nested.value) // true
isset(() => some.nested.deeper.value) // false

// Less compact but still viable except when trying to use `this` context
isset(function () { return some.nested.deeper.value }) // false

回答函数

/**
 * Checks to see if a value is set.
 *
 * @param   {Function} accessor Function that returns our value
 * @returns {Boolean}           Value is not undefined or null
 */
function isset (accessor) {
  try {
    // Note we're seeing if the returned value of our function is not
    // undefined or null
    return accessor() !== undefined && accessor() !== null
  } catch (e) {
    // And we're able to catch the Error it would normally throw for
    // referencing a property of undefined
    return false
  }
}

NPM的地方

这个回答函数可以在NPM上的isset-php包中找到。这个包包含了一些改进,比如类型检查和支持多参数。

npm install --save isset-php

完整的文档可以在README中找到。

const isset = require('isset-php')
let val = ''

// This will evaluate to true so the text will be printed.
if (isset(() => val)) {
  console.log('This val is set so I will print.')
}

解释

PHP

请注意,在PHP中,您可以在任何深度引用任何变量——甚至可以尝试引用 将非数组作为数组访问将返回一个简单的true或false:

// Referencing an undeclared variable
isset($some); // false

$some = 'hello';

// Declared but has no depth(not an array)
isset($some); // true
isset($some['nested']); // false

$some = ['nested' => 'hello'];

// Declared as an array but not with the depth we're testing for
isset($some['nested']); // true
isset($some['nested']['deeper']); // false

JavaScript

在JavaScript中,我们没有这样的自由;如果这样做,总是会得到一个错误 同样,因为引擎会立即尝试访问更深的值,然后我们才能将其包装在isset()函数中,所以……

// Common pitfall answer(ES6 arrow function)
const isset = (ref) => typeof ref !== 'undefined'

// Same as above
function isset (ref) { return typeof ref !== 'undefined' }

// Referencing an undeclared variable will throw an error, so no luck here
isset(some) // Error: some is not defined

// Defining a simple object with no properties - so we aren't defining
// the property `nested`
let some = {}

// Simple checking if we have a declared variable
isset(some) // true

// Now trying to see if we have a top level property, still valid
isset(some.nested) // false

// But here is where things fall apart: trying to access a deep property
// of a complex object; it will throw an error
isset(some.nested.deeper) // Error: Cannot read property 'deeper' of undefined
//         ^^^^^^ undefined

更多失败的选择:

// Any way we attempt to access the `deeper` property of `nested` will
// throw an error
some.nested.deeper.hasOwnProperty('value') // Error
//   ^^^^^^ undefined

// Similar to the above but safe from objects overriding `hasOwnProperty`
Object.prototype.hasOwnProperty.call(some.nested.deeper, 'value') // Error
//                                        ^^^^^^ undefined

// Same goes for typeof
typeof some.nested.deeper !== 'undefined' // Error
//          ^^^^^^ undefined

还有一些很快就会变得多余的工作替代方案:

// Wrap everything in try...catch
try {
  if (isset(some.nested.deeper)) {
    // ...
  }
} catch (e) {}

try {
  if (some.nested.deeper !== undefined && some.nested.deeper !== null) {
    // ...
  }
} catch (e) {}

// Or by chaining all of the isset which can get long
isset(some) && isset(some.nested) && isset(some.nested.deeper) // false
//                        ^^^^^^ returns false so the next isset() is never run

结论

所有其他的答案——尽管大多数是可行的……

假设你只是在检查变量是否未定义 对于一些用例是好的,但仍然可以抛出一个错误 假设您只是试图访问顶级属性,同样是 对于某些用例来说很好 强制您使用相对于PHP的isset()不太理想的方法 例如isset(some, 'nested.deep .value') 使用eval(),这是有效的,但我个人避免使用

我想我已经讲过很多了。我在回答中提出了一些观点 不要触及,因为他们-虽然相关-不是的一部分 问题(如。短路)。如果需要,我可以更新我的答案与一些链接 基于需求的更多技术方面。

我在这上面花了很多时间,所以希望它能帮助到大家。

感谢您的阅读!

try {
  const value = array.foo.object.value;
  // isset true
} catch (err) {
  // isset false
}
//
//  tring to reference non-existing variable throws ReferenceError 
//  before test function is even executed
//
//  example, if you do:
//    
//     if ( isset( someVar ) ) 
//        doStuff( someVar );
//   
//  you get a ReferenceError ( if there is no someVar... ) 
//  and isset fn doesn't get executed.
//
//  if you pass variable name as string, ex. isset( 'novar' );, 
//  this might work:
//
function isset ( strVariableName ) { 

    try { 
        eval( strVariableName );
    } catch( err ) { 
        if ( err instanceof ReferenceError ) 
           return false;
    }

    return true;

 } 
//
//

javascript isset

let test = {
  a: {
    b: [0, 1]
  }
};

console.log(test.isset('a.b'))   // true
console.log(test.isset('a.b.1')) // true
console.log(test.isset('a.b.5')) // false
console.log(test.isset('a.c'))   // false
console.log('abv'.isset('0'))    // true
(typeof SOMETHING) !== 'undefined'

它太长了,用起来写不出来。但是我们不能将typeof关键字打包到函数中,因为在函数被调用之前会抛出一个错误,如下所示:

function isdef($var) {
    return (typeof $var) !== 'undefined';
}

isdef(SOMETHING); ///// thrown error: SOMETHING is not defined

所以我想出了一个办法:

function isdef($type) {
    return $type !== 'undefined';
}

isdef(typeof SOMETHING);

它既可以处理单个变量(根本不存在的变量),也可以处理对象属性(不存在的属性)。只比PHP isset多7个字符。