目标:实现一段代码,判断一个变量的值是否为字符串 ?
方法一:
javascript
function isString1(str){ if(typeof str=="string"){ console.log("是字符串"); return true; }else{ console.log("不是字符串"); return false; } }
方法二:
javascript
//判断是否是字符串 function isString2(str){ if(Object.prototype.toString.call(str) === "[object String]"){ console.log("是字符串"); return true; }else{ console.log("不是字符串"); return false; } }
方法一也是能判断传入的变量是否为字符串的,为何说方法二更优?该如何理解方法二呢?
javascript
var a=2; var b="2"; var c=[]; var d=function(){}; var e={}; var f; isString1(a);// 不是字符串 isString1(b);// 是字符串 isString1(c);// 不是字符串 isString1(d);// 不是字符串 isString1(e);// 不是字符串 isString1(f);// 不是字符串 console.log("下面是讨论给出的参考:"); isString2(a);// 不是字符串 isString2(b);// 是字符串 isString2(c);// 不是字符串 isString2(d);// 不是字符串 isString2(e);// 不是字符串 isString2(f);// 不是字符串
问题是:谁跟你说方法二更好的? 哪个权威告诉你的?
这俩方法其实都挺好的呀!typeof
胜在速度快,Object.prototype.toString.call
性能不如 typeof
,但胜在可通用,不光可以检测 String
类型,Arguments
, Number
, Boolean
, Date
, RegExp
, Error
, Function
, Array
, Math
, JSON
, Promise
, Map
, Set
这些对象子类型通通可以一块检测了,多方便,所以许多 Library 通常采用第二种,可能只是出于偷懒的考虑,并不能说明 typeof
就不好。
单就检测字符串而言,我觉得 typeof
相对更好些,因为它速度最快!
第二好的方法嘛,我看也排不上 Object.prototype.toString.call
,而是下面这个:
function isString(s) {
return String(s) === s;
}
胜在简洁、优雅
第三才是 Object.prototype.toString.call
当然了,Object.prototype.toString.call
和 typeof
对包装对象的判定结果相反:
var s = new String("I'm a wrapper object");
typeof s === 'string'; // => false
Object.prototype.toString.call(s) === '[object String]'; // => true
变量 s
用 typeof
检测,就不是字符串类型;用 Object.prototype.toString.call
检测,就是字符串类型。哪个结果对?都对!从 typeof
的角度看,s
是一个引用类型值,不是原始值字符串,当然返回 false;从另一个角度看,s
属于对象类型下的字符串子类型,当然返回 true。
实际上,几乎不会有人显式地在程序中书写类似 s
这样的包装对象,因为所有的编码规范都不建议这么做!
所以,根本不必纠结包装对象这种特殊情况到底该返回 true 还是 false,请直接忽略这种情况!少年郎,大胆地使用 typeof
吧!
PS:
stackoverflow 上的相关链接:
Check if a variable is a string
how to detect if variable is a string
那么,isString1(new String("aaa"))
返回什么呢?
不过实际项目当中第一个完全够用啦,不如说如果js写到常常需要if isString,那代码的结构本身可能更有问题
http://www.2cto.com/kf/201308/237415.html
这里说的比较详细
第一种方法可以适应原子类型,但是对对象类型无效。
var a = new String("1")
undefined
a
String {0: "1", length: 1, [[PrimitiveValue]]: "1"}
typeof a
"object"
第二种方式无论原子,还是对象,通吃。所以,更加安全。不会出现古怪的问题,你期望一个String对象是string,但是typeof显示它不是。
Object.prototype.toString.call(a)
"[object String]"
Object.prototype.toString.call("")
"[object String]"
more reference:
http://tobyho.com/2011/01/28/checking-types-in-javascript/
多谢 @Humphry ,其实他已经说得比较清楚了。