深入浅出Javascript 'typeof '操作符

'typeof '运算符用起来的感觉还真有点像开着一部破旧的小车或是用一台早期的戴尔Inspiron系列电脑。 为了完成工作,你往往又不得不学会适应这种怪癖操作符。

但是你还是应该学会如何改善你的使用方法。

在本文中,我在介绍一款新式小函数之前,我将对'typeof '操作符做一个简短的复习。这个函数具有全加载、更坚实的可靠性和灵活性等优良品质,且直接使用了

Javascript的核心语法。

 typeOf 运算符

 它究竟怎么用呢?

因为typeof 是单运算符 ,那么它的运算域就是紧挨它本身.  而不需要额外的标点符号。

typeof2//"number"
typeof"belladonna"//"string"

 

但是当我想像调用函数那样的调用它,会是怎么样的结果呢

 typeof 运算符本身不是函数的。你可以用括号定义它的作用域,这样它看起来就像一个函数了。但是括号仅仅是一种分组的运算符 ,在给杂乱排序的优先级上仅次于逗号运算符。事实上, 你可以用任何其他标点符号来修饰它的作用域

typeof (2)//"number"

typeof(2)//"number"

typeof ("a", 3)//"number"

typeof (1 + 1)//"number"

 

它的返回值是什么呢?

返回值是一种运算域类型的独有的表述. 请看下面的列表清单

变量类型 返回值
Undefinedundefined
Nullobject
Booleanboolean
Numbernumber
Stringstring
Object (native and not callable)object
Object (native or host and
callable)
function
Object (host and not
callable)
Implementation-defined

typeof有什么问题呢?

最明显的问题就是 typeof null 居然返回 一个“object” 对象。 这明显是一个误解。在ECMAScript下一个版本,已经将这个问题的解决方案收纳,然而还是不可置疑的它将引进来一些对以前版本的兼容性问题 。

 
1var a;
2typeof a; //"undefined"
3typeof b; //"undefined"
4alert(a);//undefined
5alert(b);//ReferenceError

比起其他操作符, typeof 并没有多大的区别。当typeof 被用于任何一种object类型,它返回object。它和其他通用对象,和内置类型

 (Array, Arguments, Date, JSON, RegExp, Math, Error, and the primitive wrapper objects Number, Boolean and String)等也区别不大。

你可以看到广大程序员对下面这个返回值的抱怨。

typeofNaN//"number"

但是这并不是typeof的错,因为标准已明确的声明NaN是一个真实的数字。 

一种刚好的方式?

[[Class]]

每一个JavaScript 对象都有一个内置属性 [[Class]] 。ES5 指定有一对方括号来描述内置属性, i.e. 的抽象属性 过去指定了JavaScript 引擎的行为。通过ES5, [[Class]] 是一个String对象的值,规范了objects的定义.  对于你和我来说,这意味着内置对象都有一个唯一的不可编辑的标准值赋给它们各自的[[Class]] 属性。这可能对于我们获得[[Class]] 属性的值是非常有用的…

Object.prototype.toString

... ...事实证明,我们可以。以一个在ES 5的外观规格为Object.prototype.toString ...

  1. Ø ToObject通过了呼吁结果作为参数值 。
  2. 类的价值[类]]内部属性 Ø
  3. 返回字符串值,它是连接三根弦“对象”阶级,和“]” 

总之,目标函数默认 toString返回一个字符串,格式如下 ...

[对象[类] ]

... ... [类别]是对象类的属性。

不幸的是,专门的内置对象的toString的自己的方法大多是覆盖Object.prototype.toString ...

1 [1,2,3]的toString(); / / 1,2,3“
2  
3  日期)的toString(); / /“星期六八月06 2011年16时29分13秒格林尼治标准时间0700(PDT)的”
4  
5 / AZ / .toString(); / / / AZ /“

 
... ...幸运的是我们可以使用呼叫功能,以 迫使通用的toString在他们的功能...

1 Object.prototype.toString.call([1,2,3]); / /“[对象数组]”
2  
3 Object.prototype.toString.call( 日期); / /“对象日期]”
4  
5 Object.prototype.toString.call(AZ / /); / /“的RegExp对象]”

 
在介绍该toType功能

我们可以利用这种技术,添加一个正则表达式的下降,并创建一个微小的功能-一个新的和改进的版本typeof运算操作符 ...

1 VAR toType = 功能(OBJ){
2   返回 ({}). toString.call(OBJ)。匹配(/ \ S([A - ZA - Z的]+)/)[ 1]。与toLowerCase()
3 }

(因为一个新的模式,通用对象总是会使用 ToString 函数定义Object.prototype的,我们可以放心地使用作为缩写Object.prototype.toString ({}).的 toString)

让我们来试试... ...

01 toType({A:4}); / /“对象”
02 toType([1,2,3]); / /“阵列”
03 函数(){(toType的console.log(参数))})(); / /参数
04 toType( ReferenceError); / /“错误”
05 toType( 日期); / /“日期”
06 toType(AZ / /); / /“REGEXP”
07 toType(数学); / /“数学”
08 toType(JSON); / /“JSON”
09 toType(新的电话 号码(4)); / /“数”
10 toType( 的String(“ABC” )); / /“字符串”
11 toType( 布尔()); / /“布尔”

..现在,我们将运行相同的测试与typeof运算符(尽量不要幸灾乐祸) ... ...

01 typeof运算 {A:4} / /“对象”
02 typeof运算 [1,2,3]; / /“对象”
03 函数(){的console.log(typeof运算 参数)})(); / /对象
04 typeof运算  ReferenceError; / /“对象”
05 typeof运算 新的 日期; / /“对象”
06 typeof运算 / AZ / / /“对象”
07 typeof运算 数学; / /“对象”
08 typeof运算 的JSON / /“对象”
09 typeof运算 的新 号码(4); / /“对象”
10 typeof运算  的String(“ABC” ); / /“对象”
11 typeof运算 的新 布尔(); / /“对象”

 
鸭打字比较

鸭打字检查对一个给定的类型(像鸭子散步,像鸭子的谈判... ...)的已知属性的列表中的对象的特点。由于typeof运算操作符的作用有限,鸭,打字在JavaScript中很受欢迎。它也容易出错。例如参数的函数对象都有一个长度属性和数字索引的元素,但它仍然不是一个数组 。

使用toType是一个可靠和易于的替代鸭打字 。可靠的,因为它直接谈判的对象,这是由浏览器引擎,是不可编辑的内部属性;容易的,因为其三个词检查。

这里的一个例证-一个片段,它定义不符合标准的JSON对象。jsonParseIt函数接受一个函数作为参数,它可以用它来 ​​测试之前,用它来 ​​解析JSON字符串的JSON对象的真实性... 。

1 window.JSON = {分析:函数(){警报(“我不是真正的JSON -失败!” )}};
2  
3 功能 jsonParseIt(jsonTest){
4    (jsonTest()){
5     返回 JSON.parse(“{”A“:2}” );
6   其他 {
7     警报(“不符合标准的检测到的JSON对象!“) ;
8   }
9 }

让我们运行它,鸭打字第一... ...

jsonParseIt(函数(){ 返回 JSON&&(typeof运算 JSON.parse == “功能” )})
/ /“我没有真正的JSON - 失败!”

... ...哎呦... ...现在与toType测试... ...

jsonParseIt(函数(){ 返回 toType(JSON)== “JSON” });
/ /“不符合标准的JSON对象检测!”

toType可靠保护,对内置的JavaScript对象与冒名顶替的恶意交换?大概不会,因为行为人想必也可以交换toType功能。一个更安全的测试可能会直接调用({}).的toString ...

函数(){ 返回 ({}). toString.call(JSON)的indexOf(“JSON” )> -1}

..但即使这会失败,如果Object.prototype.toString本身就是恶意重新编写的。静止每个额外的防御帮助。

比较到的instanceof

instanceof 运算符测试的原型链中的第一个操作数为原型属性的第二个操作数(第二个操作数预计将是一个构造函数,如果它不是一个函数,将抛出一个TypeError)存在:

1  日期的 instanceof日期; / / TRUE
2  
3 [1,2,3] 的instanceof 阵列; / / TRUE
4  
5 功能 CustomType(){};
6  CustomType 的instanceof CustomType; / / TRUE

 
在它面前,这似乎是一个不错的类型检查器的内置插件举行的承诺,但也有碰壁,这种方法至少有两个:

1。不具有关联的几个内置对象(数学JSON参数)构造函数的对象-所以他们不能与类型检查的instanceof运算符。

数学的instanceof 数学/ /类型错误

2。作为@ kangax和其他人指出,一个窗口可以包括多个帧,这意味着全球多个上下文和每种类型的,因此多个构造。在这样一个环境,一个给定对象的类型是不保证的instanceof一个给定的构造... 。

1 VAR 的iFrame = document.createElement(“IFRAME” );
2 document.body.appendChild(IFRAME);
3  
4 VAR = window.frames [1]的数组。
5 VAR 阵列=  IFrameArray();
6  
7 阵列的instanceof 阵列; / /假
8 阵列的instanceof IFrameArray; / /结果为true;

 
类型检查主机对象

主机对象是浏览器的ES5标准不指定创建的对象 。所有DOM元素和全局函数的宿主对象。ES5下降到指定返回值typeof运算,适用于主机对象时,它也不建议值[类]主机对象的财产。其结果是,跨浏览器的主机对象的类型检查一般是不可靠的:

01 toType(窗口);
02 / /“全球”(镀铬)“domwindow”(Safari浏览器)“窗口”(FF/IE9)“对象”(IE7/IE8)
03  
04 toType(文件);
05 / /“的HTMLDocument”(浏览器/ FF / Safari浏览器)的“文件”(IE9)“对象”(IE7/IE8)
06  
07 toType(document.createElement('A' ));
08 / /“htmlanchorelement”(铬/ FF / Safari浏览器/ IE)“对象”(IE7/IE8)
09  
10 toType(警报);
11 / /“职能”(Chrome/FF/Safari/IE9)“对象”(IE7/IE8)

 
元素的最可靠的跨浏览器测试,可能是检查了存在的 nodeType属性 ...

功能 isElement(OBJ){
  返回 obj.nodeType;
}

 
... ...但是,鸭打字,所以没有任何保证 ;-)

一个toType功能应该在哪里生活?

为了简便起见,我的例子中定义toType,作为一个全球性的的功能。扩展Object.prototype的将你抛出的龙 -我的喜好将直接扩展对象,它反映ES5(和建立该公约的Prototype.js在这之前)。

1 Object.toType = 功能(OBJ){
2   返回 ({}). toString.call(OBJ)匹配(/ \ S([AZ |排列]+)/)[ 1]与toLowerCase();
3 }

 
另外,你可以选择 UTIL一个属于自己的命名空间添加toType的功能。

我们可以得到一个小聪明(窗口 Chrome的使用“全局”的启发。[[类 ]) 。,包装在一个全球性的的模块中的功能,我们可以找出全局对象:

1 Object.toType =(功能 toType(全球){
2   返回 功能(OBJ){
3     如果 (OBJ ===全球){
4       返回 “全球性” ;
5     }
6     返回 ({}). toString.call(OBJ)匹配(/ \ S([AZ |排列]+)/)[ 1]与toLowerCase();
7   }
8 })( 

 
让我们来试试... ...

1 Object.toType(窗口); / /“全球”(所有的浏览器)
2 Object.toType([1,2,3]); / /“阵列”(所有浏览器)
3 Object.toType(/ AZ /); / /“REGEXP”(所有浏览器)
4 Object.toType(JSON); / /“JSON”(所有浏览器)
5 / /等等。

 
没有做什么toType

toType功能不能保护从未知类型的投掷ReferenceErrors ...

Object.toType(FFF); / / ReferenceError

更确切地说,它是调用 toType抛出的错误,而不是函数本身 。反对,唯一的后卫(如与任何函数调用),养成良好的代码卫生... ...

window.fff&Object.toType(FFF);

总结

我胡说在更长的时间比我打算 - 那么恭喜,如果你这里,我希望你觉得它有用。我介绍了很多地面和可能犯了一些错误 - 请随时让我知道他们。此外,我很乐意听到其他人的冒险类型检查。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值