jQuery核心风格指南提供了两种不同的方法来检查变量是否被定义。
全局变量:typeof variable === "undefined" 局部变量:variable === undefined 属性:对象。Prop === undefined
为什么jQuery对全局变量使用一种方法,而对局部变量和属性使用另一种方法?
jQuery核心风格指南提供了两种不同的方法来检查变量是否被定义。
全局变量:typeof variable === "undefined" 局部变量:variable === undefined 属性:对象。Prop === undefined
为什么jQuery对全局变量使用一种方法,而对局部变量和属性使用另一种方法?
当前回答
简介:
当处于全局作用域时,如果变量没有声明或值为undefined,我们实际上希望返回true:
var globalVar1; //该变量声明了,但没有定义,因此值为undefined console.log(globalVar1 === undefined); //该变量未声明,因此将抛出referenceError console.log(globalVar2 === undefined);
因为在全局作用域中,我们不能100%确定是否声明了一个变量,这可能会给我们一个referenceError。当我们在未知变量上使用typeof操作符时,如果变量没有声明,就不会出现这个问题:
var globalVar1; log控制台。 log控制台。
这是因为typeof操作符在变量未声明或当前值为undefined时返回字符串未定义,而这正是我们想要的。
对于局部变量,我们就没有这个问题,因为我们事先知道这个变量是存在的。如果变量存在,我们可以简单地在相应的函数中查找。 对于对象属性,我们就没有这个问题,因为当我们试图查找一个不存在的对象属性时,我们也会得到undefined的值
var obj = {}; consoles.log(obj.myProp === undefined);
其他回答
jQuery可能希望你在函数中使用let和const变量,在JavaScript的ES6 2015设计中,不允许你使用任何局部作用域(函数)let或const变量,直到它们被声明。甚至通过Javascript提升也不允许你对它们进行类型检查!
如果你尝试这样做,JavaScript会生成一个错误,不像var变量,当提升时创建一个声明但未初始化的变量,你可以输入检查或检查它是否未定义。
如果你在函数中声明了一个let或const变量,但是在尝试访问它之后,typeof检查仍然会在JavaScript中创建一个引用错误!这是非常奇怪的行为,对我来说,为什么要这样设计是不合逻辑的。但这就是为什么jQuery认为typeof函数变量没有任何用处。例子:
function MyError(){
// WOW! This variable DOES NOT EVEN EXIST, but you can still check its type!
if(typeof x === 'undefined')
{
alert(1);// OK!
}
// ERROR!
// WOW! You cannot even check an existing "let" variable's TYPE in a local function!
if(typeof y === 'undefined')//REFERENCE ERROR!!
{
alert(2);
}
// We defined the variable so its hoisted to the top but in a dead zone
let y = 'test';
}
MyError();
// RESULT
// alert 1 fires but a REFERENCE ERROR is generated from the second alert 2 condition.
奇怪的是,一个不存在的局部变量不能使用typeof检查'undefined',但函数中声明的let变量却不能!所以这可能就是为什么我不依赖jQuery来定义什么是最好的。有边界情况。
关于JavaScript中“未定义”变量的更多奇怪之处
**undefined有两种不同的表达式和三种不同的用法,如下所示:
"typeof"和"undefined"类型:未声明且不存在的变量没有被赋值,而是有一个"type"为undefined。如果你访问一个根本不存在的变量,更不用说声明或初始化了,如果你访问它,你会生成一个REFERENCE ERROR,即使是在测试原始的默认值undefined时,它被赋给了声明的变量,直到赋值。所以检查"typeof"在这种情况下可以防止这个错误,如下所示:
// In this first test, the variable "myVariable1" does not exist yet so creates
// an error if we try and check if its assigned the default value of undefined!
if (myVariable1 === undefined) alert(true);// REFERENCE ERROR!
// Here we can elegantly catch the "undefined" type
// of the missing variable and stop the REFERENCE ERROR using "typeof".
if (typeof myVariable1 === "undefined") alert(true);// true
// Here we have declared the missing variable and notice its
// still an "undefined" type until initialized with a value.
let myVariable1;
if (typeof myVariable1 === "undefined") alert(true);// true
// Lastly, after we assign a value, the type is no longer
// "undefined" so returns false.
myVariable1 = 'hello';
if (typeof myVariable1 === "undefined") alert(true);// false
JavaScript中所有被访问但未声明的对象和类型将默认为“undefined”类型。因此,这里的教训是首先尝试检查typeof,以防止丢失变量错误!
未定义的原始值:所有尚未赋值的声明变量都在JavaScript中被赋值为未定义的原语。如果你已经声明了一个变量,但还没有初始化它,它就会被赋值为默认的原始类型undefined。这与“未定义”类型不同。未定义的基本值是保留值,但可以更改,但这不是这里要求的。注意,这只捕获所有声明但未初始化的变量:
let myVariable3;
if (myVariable3 === undefined) alert(true);// true
let myVariable4 = 'hello';
if (myVariable4 === undefined) alert(true);// false
对象和未定义的原语:最后,对象属性的行为不像JavaScript中的变量。当缺少对象属性时,对象属性不会变成未定义类型,而是简单地为未声明的变量分配原语undefined。所以他们表现得像#2:
let myObject = {};
if (myObject.myProperty === undefined) alert(true);// true
最佳实践
最后……这是一个非常好的理由,总是检查“未定义”类型和未定义的原始值变量在你的所有JavaScript代码。大多数人会说,你很少两者都需要。可能会有一天,在一个不存在的库中访问一个缺失的变量,并创建一个讨厌的JavaScript引用错误!所以我总是这样检查,并按照这个顺序,以停止JavaScript中的所有错误:
if (typeof myVariable !== "undefined" && myVariable !== undefined) {
// do something safe with myVariable!
}
在节点v6.9.1上,Typeof a === 'undefined'比a === 'undefined'快大约2倍。
对于局部变量,使用localVar === undefined进行检查是有效的,因为它们必须在局部作用域内的某个地方定义,否则它们将不被视为局部变量。
对于非本地且未在任何地方定义的变量,someVar === undefined检查将抛出异常:Uncaught ReferenceError: j未定义
下面是一些代码,可以澄清我上面所说的内容。为了更清晰,请注意内联注释。
function f (x) {
if (x === undefined) console.log('x is undefined [x === undefined].');
else console.log('x is not undefined [x === undefined.]');
if (typeof(x) === 'undefined') console.log('x is undefined [typeof(x) === \'undefined\'].');
else console.log('x is not undefined [typeof(x) === \'undefined\'].');
// This will throw exception because what the hell is j? It is nowhere to be found.
try
{
if (j === undefined) console.log('j is undefined [j === undefined].');
else console.log('j is not undefined [j === undefined].');
}
catch(e){console.log('Error!!! Cannot use [j === undefined] because j is nowhere to be found in our source code.');}
// However this will not throw exception
if (typeof j === 'undefined') console.log('j is undefined (typeof(x) === \'undefined\'). We can use this check even though j is nowhere to be found in our source code and it will not throw.');
else console.log('j is not undefined [typeof(x) === \'undefined\'].');
};
如果我们像这样调用上面的代码:
f();
输出是这样的:
x is undefined [x === undefined].
x is undefined [typeof(x) === 'undefined'].
Error!!! Cannot use [j === undefined] because j is nowhere to be found in our source code.
j is undefined (typeof(x) === 'undefined'). We can use this check even though j is nowhere to be found in our source code and it will not throw.
如果我们像这样调用上面的代码(实际上是任意值):
f(null);
f(1);
输出将是:
x is not undefined [x === undefined].
x is not undefined [typeof(x) === 'undefined'].
Error!!! Cannot use [j === undefined] because j is nowhere to be found in our source code.
j is undefined (typeof(x) === 'undefined'). We can use this check even though j is nowhere to be found in our source code and it will not throw.
当你像这样做检查:typeof x === 'undefined',你本质上是在问:请检查变量x是否存在(已定义)在源代码的某个地方。(多多少少)。如果你知道c#或Java,这种类型的检查永远不会进行,因为如果它不存在,它就不会编译。
<==小提琴我==>
因为undefined并不总是声明的,但是jQuery在它的main函数中声明了undefined。因此,它们在内部使用安全的未定义值,但在外部,它们使用typeof样式以确保安全。
使用typef -variant的另一个原因是:undefined可以被重新定义。
undefined = "foo";
var variable = "foo";
if (variable === undefined)
console.log("eh, what?!");
typeof变量的结果不能。
更新:注意,在ES5中不是这样的,全局未定义是一个不可配置,不可写的属性:
15.1.1全局对象的值属性 […] 15.1.1.3未定义 undefined的值是undefined(参见8.1)。该属性具有以下属性 {[[可写]]:false,[[可列举]]:false,[[可配置]]:false}。
但它仍然可以被一个局部变量遮蔽:
(function() {
var undefined = "foo";
var variable = "foo";
if (variable === undefined)
console.log("eh, what?!");
})()
或参数:
(function(undefined) {
var variable = "foo";
if (variable === undefined)
console.log("eh, what?!");
})("foo")