JavaScript isset() 等效

IT技术 javascript isset
2021-02-11 11:44:46

在 PHP 中你可以做到if(isset($array['foo'])) { ... }在 JavaScript 中,您经常使用if(array.foo) { ... }相同的语句,但这并不是完全相同的语句。如果array.foo确实存在但是是falseor 0(也可能是其他值),条件也将评估为 false

什么是issetJavaScript中 PHP 的完美等价物

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

6个回答

我一般使用typeof运算符:

if (typeof obj.foo !== 'undefined') {
  // your code here
}

"undefined"如果该属性不存在或其值为,它将返回undefined

(另见:和未定义的区别undefined

还有其他方法可以确定对象上是否存在属性,例如hasOwnProperty方法:

if (obj.hasOwnProperty('foo')) {
  // your code here
}

in运营商:

if ('foo' in obj) {
  // your code here
}

后两者的区别在于该hasOwnProperty方法将检查该属性是否物理存在于对象上(该属性不是继承的)。

in运营商将检查所有属性在原型链,如到达了:

var obj = { foo: 'bar'};

obj.hasOwnProperty('foo'); // true
obj.hasOwnProperty('toString'); // false
'toString' in obj; // true

如您所见,检查方法hasOwnProperty返回falsein运算符返回,该方法定义在原型链中,因为继承了 form truetoStringobjObject.prototype

这样做的问题是当您尝试检查更深层次的属性时会出现错误,例如:obj.thisdoesntexist.foo !== undefined。在 PHP 中,您可以在任何深度安全地使用 isset 或 empty 。
2021-03-28 11:44:46
IE8 没有“hasOwnPropery”
2021-04-03 11:44:46
为什么使用typeof而不是if( obj.foo !== undefined )
2021-04-05 11:44:46
啊。总有一天我会写一段真正跨浏览器的 Javascript。直到那时...
2021-04-05 11:44:46
确切地说,isset($abc->def->ghi->jkl)与 JavaScript 的typeof运算符不同,PHP 允许在不引发异常的情况下停止脚本你必须使用类似的东西 try{ abc.def.ghi.jkl; isset=true } catch(e){ isset=false }
2021-04-09 11:44:46

古老的线程,但有新的方法可以运行等效的isset().

ESNext(2019 年 12 月 4 日第 4 阶段)

两种新语法使我们能够极大地简化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 包

此答案功能可作为isset-phpNPM 上软件包使用。该包包含一些改进,例如类型检查和支持多个参数。

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 中,您可以引用任何深度的任何变量 - 即使尝试访问非数组,因为数组将返回一个简单的truefalse

// 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 中,我们没有那种自由;如果我们这样做,我们总是会得到一个错误,因为引擎会deeper在我们将它包装到我们的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

结论

所有其他答案-尽管大多数都是可行的...

  1. 假设您只是检查变量是否未定义,这对于某些用例来说很好,但仍然会引发错误
  2. 假设您只是尝试访问顶级属性,这对于某些用例来说同样适用
  3. 强制您使用相对于 PHP 的不太理想的方法,isset()
    例如isset(some, 'nested.deeper.value')
  4. 使用eval()哪个有效,但我个人避免

我想我涵盖了很多。我在回答中提出了一些我没有涉及的观点,因为它们 - 尽管相关 - 不是问题的一部分(例如短路)。不过,如果需要,我可以根据需要使用指向一些更具技术性的方面的链接来更新我的答案。

我花了很多时间在这上面,所以希望它可以帮助人们。

感谢您的阅读!

参考来源

    module.exports = function isset () {
  //  discuss at: http://locutus.io/php/isset/
  // original by: Kevin van Zonneveld (http://kvz.io)
  // improved by: FremyCompany
  // improved by: Onno Marsman (https://twitter.com/onnomarsman)
  // improved by: Rafał Kukawski (http://blog.kukawski.pl)
  //   example 1: isset( undefined, true)
  //   returns 1: false
  //   example 2: isset( 'Kevin van Zonneveld' )
  //   returns 2: true

  var a = arguments
  var l = a.length
  var i = 0
  var undef

  if (l === 0) {
    throw new Error('Empty isset')
  }

  while (i !== l) {
    if (a[i] === undef || a[i] === null) {
      return false
    }
    i++
  }

  return true
}

phpjs.org 大部分已退休,转而支持 locutus 这是新链接http://locutus.io/php/var/isset

isset(abc.def.ghi)如果abc.def未定义,则在调用时会引发异常但是,通过将此解决方案与接受字符串形式的变量名称的解决方案相结合,它将与 PHP 版本相同。
2021-04-09 11:44:46
if (!('foo' in obj)) {
  // not set.
}
//
//  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;

 } 
//
//