等同于JavaScript isset()


552

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

issetJavaScript 与PHP的完美等同是什么?

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


1
我编写了一个函数,无论查询的深度如何,都将测试对象属性的存在:stackoverflow.com/a/12681101/1268003使用我的代码,并结合该线程中@CMS共享的一些知识,您可以轻松编写一个全局变量该功能非常类似于PHP:s isset。
马丁·安德森

3
如果你使用Underscore.js尝试_.isUndefined(arr.foo)
维塔利费德林

可选链接可能是大多数人想要的stackoverflow.com/a/60845999/2100372
zoran404

Answers:


938

我通常使用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返回false,而in操作员会返回,该方法在原型链中定义,因为它继承了form 。truetoStringobjObject.prototype


23
为什么使用typeof而不是if( obj.foo !== undefined )
马特·鲍尔

7
啊。有一天,我将写一篇真正的跨浏览器Javascript。直到那时...
Matt Ball

37
这样做的问题是,当您尝试检查更深的属性时会出现错误,例如:obj.thisdoesntexist.foo!== undefined。在PHP中,可以在任何深度安全地使用isset或empty。
恩里克

6
IE8没有“ hasOwnPropery”
max4ever,2012年

12
确实,isset($abc->def->ghi->jkl)与JavaScript的typeof运算符不同,PHP允许不引发异常和停止脚本。您必须使用类似的东西 try{ abc.def.ghi.jkl; isset=true } catch(e){ isset=false }
Steven Pribilinskiy 2014年

43

使用旧线程,但是有新方法可以运行等效线程 isset()

ESNext(2019年12月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
 */
function isset (accessor) {
  try {
    // Note we're seeing if the returned value of our function is not
    // undefined
    return typeof accessor() !== 'undefined'
  } catch (e) {
    // And we're able to catch the Error it would normally throw for
    // referencing a property of undefined
    return false
  }
}

说明

的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

JS

在JavaScript中,我们没有这种自由,如果这样做,我们总会出错,因为JS 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

Object.hasOwnProperty('value', some.nested.deeper) // Error
//                                  ^^^^^^ undefined

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

还有一些可以快速获得冗余的可行替代方案:

// Wrap everything in try...catch
try { isset(some.nested.deeper) } catch (e) {}
try { typeof some.nested.deeper !== 'undefined' } 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()哪种有效,但我个人避免使用

我想我涵盖了很多。我在回答中提出了一些要点,但我没有提及,因为它们虽然相关,但不是问题的一部分。不过,如果需要,我可以根据需要通过指向一些更多技术方面的链接来更新我的答案。

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

谢谢您的阅读!


25

参考资料

    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


6
isset(abc.def.ghi)如果abc.def未定义,则在调用时会引发异常。但是,通过将此解决方案与可以接受字符串形式的变量名的解决方案相结合,它将与PHP版本相同。
Steven Pribilinskiy 2014年


8
//
//  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;

 } 
//
//


6

我总是使用此通用函数来防止对原始变量以及数组和对象产生错误。

isset = function(obj) {
  var i, max_i;
  if(obj === undefined) return false;
  for (i = 1, max_i = arguments.length; i < max_i; i++) {
    if (obj[arguments[i]] === undefined) {
        return false;
    }
    obj = obj[arguments[i]];
  }
  return true;
};

console.log(isset(obj));                   // returns false
var obj = 'huhu';
console.log(isset(obj));                   // returns true
obj = {hallo:{hoi:'hoi'}};
console.log(isset(obj, 'niet'));           // returns false
console.log(isset(obj, 'hallo'));          // returns true
console.log(isset(obj, 'hallo', 'hallo')); // returns false
console.log(isset(obj, 'hallo', 'hoi'));   // returns true


4

这是一个测试变量是否存在的防弹解决方案:

var setOrNot = typeof variable !== typeof undefined ? true : false;

不幸的是,您不能简单地将其封装在一个函数中。

您可能会想到做这样的事情:

function isset(variable) {
    return typeof variable !== typeof undefined ? true : false;
}

但是,如果variable未定义变量,则会产生参考错误,因为您无法将不存在的变量传递给函数:

未捕获的ReferenceError:未定义foo

另一方面,它确实允许您测试函数参数是否未定义:

var a = '5';

var test = function(x, y) {
    console.log(isset(x));
    console.log(isset(y));
};

test(a);

// OUTPUT :
// ------------
// TRUE
// FALSE

即使没有将for的y值传递给function test,我们的isset函数在这种情况下也可以完美运行,因为y在函数中test称为undefinedvalue。


次要:“?true:false`是多余的。的结果!==已经是布尔值。
制造商

4
(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多7个字符isset


这对我有用,用它来检查是否存在特定的json响应。
朱利叶斯


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

4
也添加一些描述。
Shree Krishna

如先前的几个回答所述,如果使用从未声明过的变量进行调用,则会引发ReferenceError。例如isset(someVar)someVar从未声明过的位置。但是,考虑到这样做eval,您可能希望传递一个字符串。显示用法。您打算使用isset('someVar')吗?如果是这样,这看起来类似于先前的答案 -您的答案是新的吗?
制造商



2

提供对象路径作为字符串,然后您可以将此字符串分解为路径并hasOwnProperty在每个步骤中解析,同时每次迭代覆盖对象本身。

如果您在ES6环境中进行编码,请查看一下stackoverflow Ques

var a;

a = {
    b: {
        c: 'e'
    }
};

function isset (obj, path) {
    var stone;

    path = path || '';

    if (path.indexOf('[') !== -1) {
        throw new Error('Unsupported object path notation.');
    }

    
    path = path.split('.');
    
    do {
        if (obj === undefined) {
            return false;
        }

        stone = path.shift();
        
        if (!obj.hasOwnProperty(stone)) {
            return false;
        }
        
        obj = obj[stone];
        
    } while (path.length);

    return true;
}

console.log(
    isset(a, 'b') == true,
    isset(a, 'b.c') == true,
    isset(a, 'b.c.d') == false,
    isset(a, 'b.c.d.e') == false,
    isset(a, 'b.c.d.e.f') == false
);


2

我使用了可以检查变量和对象的函数。使用jQuery非常方便

    function _isset (variable) {
        if(typeof(variable) == "undefined" || variable == null)
            return false;
        else
            if(typeof(variable) == "object" && !variable.length) 
                return false;
            else
                return true;
    };

如先前的几个回答所述,如果使用从未声明过的变量进行调用,则会引发ReferenceError。
制造商史蒂夫

1

当我访问对象的更深的属性时,这对我来说确实是一个问题,因此我创建了一个函数,该函数将返回该属性值(如果存在),否则将返回false。您可以使用它来节省时间,

//Object on which we want to test
var foo = {
    bar: {
        bik: {
            baz: 'Hello world'
        }
    }
};


/*
USE: To get value from the object using it properties supplied (Deeper),
    if found it will return the property value if not found then will return false

You can use this function in two ways
WAY - 1:
Passing an object as parameter 1 and array of the properties as parameter 2
EG: getValueFromObject(foo, ['bar', 'bik', 'baz']);
WAY - 2: (This will work only if, your object available in window object)
Passing an STRING as parameter 1(Just similarly how we retrieve value form object using it's properties - difference is only the quote)
EG: getValueFromObject('foo.bar.bik.baz');
*/
function getValueFromObject(object, properties) {
    if(typeof(object) == 'string') {            //Here we extract our object and it's properties from the string
        properties = object.split('.');
        object = window[properties[0]];
        if(typeof(object) == 'undefined') {
            return false;
        }
        properties.shift();
    }
    var property = properties[0];
    properties.shift();
    if(object != null && typeof(object[property]) != 'undefined') {
        if(typeof(object[property]) == 'object') {
            if(properties.length != 0) {
                return getValueFromObject(object[property], properties);    //Recursive call to the function
            } else {
                return object[property];
            }
        } else {
            return object[property];
        }
    } else {
        return false;
    }
}
console.log(getValueFromObject('fooo.bar.bik.baz'));        //false
console.log(getValueFromObject('foo.bar.bik.baz'));         //Hello world
console.log(getValueFromObject('foo'));                     //false
console.log(getValueFromObject('foo.bar.bik'));             //returns an object { baz: 'Hello World' }
console.log(getValueFromObject(foo, ['bar', 'bik']));       //returns an object { baz: 'Hello World' }
console.log(getValueFromObject(foo, ['bar', 'bik', 'baz']));//Hello world

1

如果要检查元素是否存在,只需使用以下代码:

if (object) {
  //if isset, return true
} else {
  //else return false
}

这是示例:

function switchDiv() {
    if (document.querySelector("#divId")) {
        document.querySelector("#divId").remove();
    } else {
        var newDiv = document.createElement("div");
        newDiv.id = "divId";
        document.querySelector("body").appendChild(newDiv);
    }
}

document.querySelector("#btn").addEventListener("click", switchDiv);
#divId {
    background: red;
    height: 100px;
    width: 100px;
    position: relative;
    
}
<body>
  <button id="btn">Let's Diiiv!</button>
</body>


0
if (var) {
  // This is the most concise equivalent of Php's isset().
} 

0

PHP手册说:

isset —确定是否设置了变量并且不为NULL

并进行如下操作:

bool isset ( mixed $var [, mixed $... ] )

该参数$var是要检查的变量。它可以有任意数量的参数。

TRUE如果var存在并且具有除以外的其他值,则isset()返回NULLFALSE除此以外。

一些例子:

$foo = 'bar';
var_dump(isset($foo));        -> true

$baz = null;
var_dump(isset($baz));        -> false

var_dump(isset($undefined));  -> false

考虑到这一点,显然,不可能编写与php isset()函数完全相同的代码。例如,当我们这样调用时:

if (isset(some_var)) {

}

function issset() {
    // function definition
}

Javascript触发器Uncaught ReferenceError: some_var is not defined at (file_name):line_number。关于此行为的重要且非凡的事情是,当尝试将不存在的变量传递给正常函数时,会触发错误。

但是在PHP中 isset()中实际上不是常规函数,而是语言构造。这意味着它们是PHP语言本身的一部分,不遵循正常的函数规则,因此可以避免不为不存在的变量触发错误。当试图找出一个变量是否存在时,这一点很重要。但是在javscript中,它首先触发一个错误,即使用不存在的变量进行函数调用。

我的观点是,我们不能将其编写为等效的javscript函数,但可以做类似的事情

if (typeof some_var !== 'undefined') {
   // your code here
}

如果您想要完全相同的效果,PHP还检查varable是否不 NULL

例如

$baz = null;
var_dump(isset($baz));        -> false

因此,我们可以将其合并到javascript中,如下所示:

if (typeof some_var !== 'undefined' && some_var !== null) {
   // your code here
}

0

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

0

在ES6中要小心,如果您要检查let变量的声明并进行声明(如果不是),则所有以前的解决方案均不起作用

let myTest = 'text';

if(typeof myTest === "undefined") {
    var myTest = 'new text'; // can't be a let because let declare in a scope
}

你会看到一个错误

未捕获的SyntaxError:标识符'myTest'已被声明

解决的办法是通过一个变种来改变它

var myTest = 'text'; // I replace let by a var

if(typeof myTest === "undefined") {
    var myTest = 'new text';
}

另一个解决方案,如果您可以更改一个变量的let,则需要删除您的变量

let myTest = 'text';

if(typeof myTest === "undefined") {
    myTest = 'new text'; // I remove the var declaration
}

-1
    isset('user.permissions.saveProject', args);

    function isset(string, context) {
        try {
            var arr = string.split('.');
            var checkObj = context || window;

            for (var i in arr) {
                if (checkObj[arr[i]] === undefined) return false;
                checkObj = checkObj[arr[i]];
            }

            return true;
        } catch (e) {
            return false;
        }
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.