Home >Web Front-end >JS Tutorial >Summary of usage of typeof in js_javascript skills
JavaScript中的typeof其实非常复杂,它可以用来做很多事情,但同时也有很多怪异的表现.本文列举出了它的多个用法,而且还指出了存在的问题以及解决办法.
> typeof undefined
'undefined'
> typeof null // well-known bug
'object'
> typeof true
'boolean'
> typeof 123
'number'
> typeof "abc"
'string'
> typeof function() {}
'function'
> typeof {}
'object'
> typeof []
'object'
> typeof unknownVariable
'undefined'
1.检查一个变量是否存在,是否有值.
typeof在两种情况下会返回"undefined":一个变量没有被声明的时候,和一个变量的值是undefined的时候.例如:
> typeof undeclaredVariable === "undefined" true > var declaredVariable; > typeof declaredVariable 'undefined' > typeof undefined 'undefined'
还有其他办法检测某个值是否是undefined:
> var value = undefined; > value === undefined true
但这种方法如果使用在一个未声明的变量上的时候,就会抛出异常,因为只有typeof才可以正常检测未声明的变量的同时还不报错:
> undeclaredVariable === undefined ReferenceError: undeclaredVariable is not defined
注意:未初始化的变量,没有被传入参数的形参,不存在的属性,都不会出现上面的问题,因为它们总是可访问的,值总是undefined:
> var declaredVariable; > declaredVariable === undefined true > (function (x) { return x === undefined }()) true > ({}).foo === undefined true
译者注:因此,如果想检测一个可能没有被声明的全局变量是否存在,也可以使用 if(window.maybeUndeclaredVariable){}
问题: typeof在完成这样的任务时显得很繁杂.
解决办法: 这样的操作不是很常见,所以有人觉的没必要再找更好的解决办法了.不过也许有人会提出一个专门的操作符:
> defined undeclaredVariable false > var declaredVariable; > defined declaredVariable false
或者,也许有人还需要一个检测变量是否被声明的操作符:
> declared undeclaredVariable false > var declaredVariable; > declared declaredVariable true
译者注:在perl里,上面的defined操作符相当于defined(),上面的declared操作符相当于exists(),
2.判断一个值不等于undefined也不等于null
问题:如果你想检测一个值是否被定义过(值不是undefined也不是null),那么你就遇到了typeof最有名的一个怪异表现(被认为是一个bug):typeof null返回了"object":
> typeof null 'object'
译者注:这只能说是最初的JavaScript实现的bug,而现在标准就是这样规范的.V8曾经修正并实现过typeof null === "null",但最终证明不可行.http://wiki.ecmascript.org/doku.php?id=harmony:typeof_null
解决办法: 不要使用typeof来做这项任务,用下面这样的函数来代替:
function isDefined(x) { return x !== null && x !== undefined; }
另一个可能性是引入一个“默认值运算符”,在myValue未定义的情况下,下面的表达式会返回defaultValue:
myValue ?? defaultValue
上面的表达式等价于:
(myValue !== undefined && myValue !== null) ? myValue : defaultValue
又或者:
myValue ??= defaultValue
其实是下面这条语句的简化:
myValue = myValue ?? defaultValue
当你访问一个嵌套的属性时,比如bar,你或许会需要这个运算符的帮助:
obj.foo.bar
如果obj或者obj.foo是未定义的,上面的表达式会抛出异常.一个运算符.??可以让上面的表达式在遍历一层一层的属性时,返回第一个遇到的值为undefined或null的属性:
obj.??foo.??bar
上面的表达式等价于:
(obj === undefined || obj === null) ? obj : (obj.foo === undefined || obj.foo === null) ? obj.foo : obj.foo.bar
3. 객체 값과 원시 값 구별
x가 객체 값인지 감지하는 데 다음 함수가 사용됩니다.
function isObject(x) { return (typeof x === "function" || (typeof x === "object" && x !== null) }
문제: 위의 감지는 더 많습니다. typeof는 함수와 객체를 서로 다른 유형으로 간주하고 typeof null은 "객체"를 반환하기 때문에 복잡합니다.
해결 방법: 다음 방법도 개체 값을 검색하는 데 자주 사용됩니다.
function isObject2(x) { return x === Object(x); }
경고: object를 감지하기 위해 object를 사용할 수 있다고 생각할 수도 있지만, object의 프로토타입을 사용하여 인스턴스 관계를 결정합니다. 예, 프로토타입 없이 객체를 어떻게 처리해야 할까요?
> var obj = Object.create(null); > Object.getPrototypeOf(obj) null
obj는 실제로 객체이지만 어떤 값의 인스턴스도 아닙니다.
> typeof obj 'object' > obj instanceof Object false
실제로는 이러한 객체가 거의 발생하지 않지만 존재하고 목적이 있습니다.
번역자 주: Object.prototype은 기본적으로 존재하는 객체이며 프로토타입이 없습니다
>Object.getPrototypeOf(Object.prototype)null>typeof Object.prototype'object'>Object.prototype instanceof Object false
4. 원시값의 유형은 무엇인가요?
typeof는 원시값의 유형을 확인하는 가장 좋은 방법입니다.
> typeof "abc" 'string' > typeof undefine 'undefine'
문제: typeof null의 이상한 동작을 알고 있어야 합니다.
> typeof null // 주의하세요! 'object'
해결책: 다음 함수로 이 문제를 해결할 수 있습니다(이 사용 사례에만 해당).
function getPrimitiveTypeName(x) { var typeName = typeof x; switch(typeName) { 케이스 "정의되지 않음": 케이스 "부울": 케이스 "문자열": 케이스 "객체": if ( x === null) { return "null"; } default: // 전달된 이전 판단 중 없음 new TypeError("매개변수가 기본 값이 아닙니다: " x) }
더 나은 해결책 방법: 원래 값의 유형을 반환하는 것 외에도 객체 값의 내부 [[Class]] 속성을 반환할 수 있는 함수 getTypeName()을 구현합니다. 이 함수를 구현하는 방법은 다음과 같습니다(번역자 참고 사항: $. jQuery로 입력하면 이렇게 구현됩니다)
5. 값이 함수인지 여부
typeof를 사용하면 값이 함수인지 확인할 수 있습니다.> > typeof Object.prototype.toString 'function'
원칙적으로는 instanceof Function도 이 요구 사항을 감지할 수 있습니다. 언뜻 보기에는 작성 방법이 더 우아해 보입니다. 모든 프레임과 창에는 자체 전역 변수가 있습니다. 따라서 한 프레임에서 다른 프레임으로 객체를 전달하면 두 프레임의 생성자가 다르기 때문에 인스턴스가 제대로 작동하지 않습니다. 이것이 바로 Array.isArray가 있는 이유입니다. () 객체가 특정 생성자의 인스턴스인지 확인하는 프레임워크 간 방법이 있으면 좋을 것입니다. 위의 getTypeName()은 해결 방법이 있지만 더 근본적인 해결책이 있을 수도 있습니다. 🎜>
6. 개요
다음은 현재 JavaScript에서 가장 시급한 요구사항이며 typeof의 현재 책임 중 일부 기능을 대체할 수 있습니다.
isObject()
getTypeName()
크로스 프레임이 가능하고 객체가 다음과 같은지 감지합니다. 지정됨 생성자 인스턴스
의 메커니즘은 변수가 선언되었는지 여부를 확인합니다. 이러한 요구 사항은 자체 연산자를 가질 필요가 없을 수도 있습니다.