【发布时间】:2011-05-02 19:54:18
【问题描述】:
如何判断一个变量是字符串还是 JavaScript 中的其他东西?
【问题讨论】:
标签: javascript string
如何判断一个变量是字符串还是 JavaScript 中的其他东西?
【问题讨论】:
标签: javascript string
这对我有用:
if (typeof myVar === 'string' || myVar instanceof String)
// it's a string
else
// it's something else
【讨论】:
instanceof 检查是毫无意义的噪音,除非您遵循一些非常不寻常的编码实践,而这个答案并不能解释它的作用或原因你可能会使用它。您需要它的唯一原因是如果您使用对象包装的字符串,但对象包装的字符串是没有人使用的毫无价值的功能,Google 和 Crockford 都谴责为不好的做法(google-styleguide.googlecode.com/svn/trunk/…,crockford.com/javascript/recommend.html)。
typeof 和instanceof 如果您的代码可能被其他人调用,感觉就像是一个好建议。 @MarkAmery 的 postmessage 边缘情况很重要,如果你问“我刚刚postmessaged 是什么?” - 但是您希望在界面上处理它并且不允许传播。在其他地方,处理未弃用的编码方法似乎是正确的,即使一些 JS 美学不赞成它们。切勿将您的代码注释为接受字符串,除非它确实如此!
你可以使用typeof操作符:
var booleanValue = true;
var numericalValue = 354;
var stringValue = "This is a String";
var stringObject = new String( "This is a String Object" );
alert(typeof booleanValue) // displays "boolean"
alert(typeof numericalValue) // displays "number"
alert(typeof stringValue) // displays "string"
alert(typeof stringObject) // displays "object"
来自this webpage 的示例。 (示例稍作修改)。
在使用new String() 创建的字符串的情况下,这将无法按预期工作,但很少使用,建议不要[1][2]。如果您愿意,请参阅其他答案以了解如何处理这些问题。
【讨论】:
new String('foo') 这样的对象包装字符串“失败”,但这并不重要,因为对象包装字符串是一个你不应该使用的毫无价值的功能。 Google 风格指南 forbids them、Douglas Crockford wants them deprecated,没有图书馆使用它们。假装它们不存在,并无所畏惧地使用typeof。
由于 580 多人投票给了错误的答案,并且 800 多人投票给了一个有效但像猎枪式的答案,我认为可能值得以一种每个人都能理解的更简单的形式重新编写我的答案。
function isString(x) {
return Object.prototype.toString.call(x) === "[object String]"
}
或者,内联(我为此设置了 UltiSnip):
Object.prototype.toString.call(myVar) === "[object String]"
仅供参考,Pablo Santa Cruz 的回答是错误的,因为 typeof new String("string") 是 object
DRAX 的答案准确且实用,应该是正确答案(因为 Pablo Santa Cruz 绝对是不正确的,我不会反对普选。)
但是,这个答案也绝对正确,实际上是最好的答案(也许除了使用lodash/underscore 的建议)。 免责声明:我为 lodash 4 代码库做出了贡献。
我最初的答案(显然是在很多人头上飞过)如下:
我是从 underscore.js 转码的:
['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'].forEach(
function(name) {
window['is' + name] = function(obj) {
return toString.call(obj) == '[object ' + name + ']';
};
});
这将定义 isString、isNumber 等。
在 Node.js 中,这可以作为一个模块来实现:
module.exports = [
'Arguments',
'Function',
'String',
'Number',
'Date',
'RegExp'
].reduce( (obj, name) => {
obj[ 'is' + name ] = x => toString.call(x) == '[object ' + name + ']';
return obj;
}, {});
[编辑]:Object.prototype.toString.call(x) 也可用于区分函数和异步函数:
const fn1 = () => new Promise((resolve, reject) => setTimeout(() => resolve({}), 1000))
const fn2 = async () => ({})
console.log('fn1', Object.prototype.toString.call(fn1))
console.log('fn2', Object.prototype.toString.call(fn2))
【讨论】:
global || window 而不是window,但这将是解决您不应该解决的问题的坏方法'一开始就没有)。
Object.prototype 中重新定义toString。所以,我认为依靠toString 来检查对象的类型充其量是一种不好的做法。
我推荐使用 jQuery 或 lodash/Underscore 的内置函数。它们更易于使用和阅读。
任何一个函数都将处理 DRAX 提到的情况...也就是说,它们都检查 (A) 变量是字符串文字还是 (B) 它是 String 对象的实例。在任何一种情况下,这些函数都会正确地将值识别为字符串。
lodash / Underscore.js
if(_.isString(myVar))
//it's a string
else
//it's something else
jQuery
if($.type(myVar) === "string")
//it's a string
else
//it's something else
【讨论】:
_.every() 起初使用起来有点令人困惑,像 _.isBoolean() 这样简单的东西让我公司的开发人员感到困惑。开发人员错误地认为如果该值是布尔值并且为假,那将是假的。对我来说,英语比德语更容易阅读,因为我不懂德语。学习 JavaScript,一切都会有意义。
function isString (obj) {
return (Object.prototype.toString.call(obj) === '[object String]');
}
我在这里看到了:
http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/
【讨论】:
Object.prototype.toString.call(obj) === '[object String]' 周围加上括号?
最好的方法:
var s = 'String';
var a = [1,2,3];
var o = {key: 'val'};
(s.constructor === String) && console.log('its a string');
(a.constructor === Array) && console.log('its an array');
(o.constructor === Object) && console.log('its an object');
(o.constructor === Number || s.constructor === Boolean) && console.log('this won\'t run');
每一个都是由其适当的类函数构造的,例如“new Object()”等。
另外,鸭子打字: “如果它看起来像鸭子,走路像鸭子,闻起来像鸭子——它一定是一个数组” 意思是,检查它的属性。
希望这会有所帮助。
请记住,您也可以随时使用多种方法的组合。下面是一个使用 typeof 的 inline map 动作示例:
var type = { 'number': Math.sqrt.bind(Math), ... }[ typeof datum ];
这是一个更“真实”的使用内联地图的示例:
function is(datum) {
var isnt = !{ null: true, undefined: true, '': true, false: false, 0: false }[ datum ];
return !isnt;
}
console.log( is(0), is(false), is(undefined), ... ); // >> true true false
这个函数将使用 [ custom ] "type-casting" -- 而不是 "type-/-value-mapping" -- 来确定一个变量是否真的“存在”。现在你可以在null 和0 之间分开那讨厌的头发!
很多时候你甚至不关心它的类型。另一种规避打字的方法是结合 Duck-Type 集:
this.id = "998"; // use a number or a string-equivalent
function get(id) {
if (!id || !id.toString) return;
if (id.toString() === this.id.toString()) http( id || +this.id );
// if (+id === +this.id) ...;
}
Number.prototype 和 String.prototype 都有一个.toString() method。您只需确保数字的等效字符串相同,然后确保将其作为Number 传递给http 函数。换句话说,我们甚至不关心它的类型是什么。
希望能给你更多的工作机会:)
【讨论】:
(o.constructor === Number || s.constructor === Boolean))。有趣的是,parseInt 和 NaN 是脆弱但强大的工具。请记住,Not-a-Number 不是 Not-a-Number,可以定义 undefined。
if(thing.call) { 'its a function'; } 或 if(thing.defineProperties) { 'its an object'; }。感谢您的投入,axkibe!
老实说,我不明白为什么在这种情况下不能简单地使用 typeof:
if (typeof str === 'string') {
return 42;
}
是的,它会在对象包装的字符串(例如new String('foo'))上失败,但这些被广泛认为是一种不好的做法,大多数现代开发工具可能不鼓励使用它们。 (如果你看到了,请修复它!)
Object.prototype.toString 把戏是所有前端开发人员在其职业生涯中的某一天都犯过的错误,但不要让它被它巧妙的修饰骗了你:它会在出现问题时立即崩溃——修补对象原型:
const isString = thing => Object.prototype.toString.call(thing) === '[object String]';
console.log(isString('foo'));
Object.prototype.toString = () => 42;
console.log(isString('foo'));
【讨论】:
typeof)。尽管如此。谢谢。
Object.prototype.toString 使其返回不同的结果......坦率地说,这就是他们的问题!恕我直言,这种可能性不应成为决定使用哪种方法的因素。 (我个人不打扰;我采用您展示的简单方法 - 但我不是在编写库代码。)
编辑:目前的做法是typeof value === 'string'。例如:
const str = 'hello';
if (typeof str === 'string') { ... }
如果你在node.js环境下工作,你可以简单地使用utils中的内置函数isString。
const util = require('util');
if (util.isString(myVar)) {}
【讨论】:
typeof value === 'string'。”
x = new String('x'); x.isString(x); 返回 false。有 util.types.isStringObject() 但对于 x = 'x' 类型字符串返回 false。两个完全不提供任何实用程序的实用程序函数...
今天 2020 年 9 月 17 日,我在 Chrome v85、Safari v13.1.2 和 Firefox v80 上对 MacOs HighSierra 10.13.6 执行所选解决方案的测试。
适用于所有浏览器(以及两个测试用例)
typeof||instanceof (A, I) 和 x===x+'' (H) 最快/最快_.isString(lodash 库)中等/快速更新:2020.11.28 我更新了 x=123 Chrome 列的结果 - 对于解决方案 I 之前可能存在错误值(=69M 太低) - 我使用 Chrome 86.0 重复测试。
我为解决方案执行了 2 个测试用例 A B C D E F G H I J K L
下面的 sn-p 给出了解决方案之间的差异
// https://stackoverflow.com/a/9436948/860099
function A(x) {
return (typeof x == 'string') || (x instanceof String)
}
// https://stackoverflow.com/a/17772086/860099
function B(x) {
return Object.prototype.toString.call(x) === "[object String]"
}
// https://stackoverflow.com/a/20958909/860099
function C(x) {
return _.isString(x);
}
// https://stackoverflow.com/a/20958909/860099
function D(x) {
return $.type(x) === "string";
}
// https://stackoverflow.com/a/16215800/860099
function E(x) {
return x?.constructor === String;
}
// https://stackoverflow.com/a/42493631/860099
function F(x){
return x?.charAt != null
}
// https://stackoverflow.com/a/57443488/860099
function G(x){
return String(x) === x
}
// https://stackoverflow.com/a/19057360/860099
function H(x){
return x === x + ''
}
// https://stackoverflow.com/a/4059166/860099
function I(x) {
return typeof x == 'string'
}
// https://stackoverflow.com/a/28722301/860099
function J(x){
return x === x?.toString()
}
// https://stackoverflow.com/a/58892465/860099
function K(x){
return x && typeof x.valueOf() === "string"
}
// https://stackoverflow.com/a/9436948/860099
function L(x) {
return x instanceof String
}
// ------------------
// PRESENTATION
// ------------------
console.log('Solutions results for different inputs \n\n');
console.log("'abc' Str '' ' ' '1' '0' 1 0 {} [] true false null undef");
let tests = [ 'abc', new String("abc"),'',' ','1','0',1,0,{},[],true,false,null,undefined];
[A,B,C,D,E,F,G,H,I,J,K,L].map(f=> {
console.log(
`${f.name} ` + tests.map(v=> (1*!!f(v)) ).join` `
)})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js" integrity="sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==" crossorigin="anonymous"></script>
This shippet only presents functions used in performance tests - it not perform tests itself!
以下是 chrome 的示例结果
【讨论】:
new String("string") 创建的字符串,x + '' === x 失败。也许它应该仅限于正确的测试,或者至少为每个测试的结果添加列,用于一个简单的测试套件,例如null、undefined、123、new Object()(应该都给false)和""、"abc"、new String("")、new String("abc")(都应该给@987654)。跨度>
== 而不是 ===,测试 A 似乎得到了轻微的加速(至少在 macOS 上的 Chrome 中)——但不确定这是否重要。
这是一个很好的例子说明为什么性能很重要:
如果没有正确完成,像测试字符串这样简单的事情可能会很昂贵。
例如,如果我想编写一个函数来测试某个内容是否为字符串,我可以通过以下两种方式之一来实现:
1) const isString = str => (Object.prototype.toString.call(str) === '[object String]');
2)const isString = str => ((typeof str === 'string') || (str instanceof String));
这两个都非常简单,那么什么可能会影响性能?一般来说,函数调用可能很昂贵,特别是如果你不知道里面发生了什么。在第一个示例中,有一个对 Object 的 toString 方法的函数调用。在第二个示例中,没有函数调用,因为 typeof 和 instanceof 是运算符。运算符的速度明显快于函数调用。
在测试性能时,示例 1 比示例 2 慢 79%!
【讨论】:
typeof str === 'string' || str instanceof String(在if (..)情况下可以去掉我喜欢的括号);无论如何,检查#2 中的原始类型和对象类型是清楚且足够的。无论如何,这些检查应该是“罕见的”。
Boolean(str.charCodeAt) 解决方案的唯一问题是它不能处理 undefined/null 的情况;否则我可以只说const isString = str => str.charCodeAt !== undefined 以获得相同的性能
我喜欢使用这个简单的解决方案:
var myString = "test";
if(myString.constructor === String)
{
//It's a string
}
【讨论】:
undefined 和null 的方法,并且仍然得到空字符串的正确答案('' 和new String(''))。跨度>
(mystring || false) && mystring.constructor === String。我使用 false 以防它用于必须返回布尔值的函数。
.constructor 返回不同的答案?这将是相当令人惊讶的。
if (s && typeof s.valueOf() === "string") {
// s is a string
}
适用于字符串文字 let s = 'blah' 和对象字符串 let s = new String('blah')
【讨论】:
取自lodash:
function isString(val) {
return typeof val === 'string' || ((!!val && typeof val === 'object') && Object.prototype.toString.call(val) === '[object String]');
}
console.log(isString('hello world!')); // true
console.log(isString(new String('hello world'))); // true
【讨论】:
你可以使用这个函数来确定任何东西的类型:
var type = function(obj) {
return Object.prototype.toString.apply(obj).replace(/\[object (.+)\]/i, '$1').toLowerCase();
};
检查变量是否为字符串:
type('my string') === 'string' //true
type(new String('my string')) === 'string' //true
type(`my string`) === 'string' //true
type(12345) === 'string' //false
type({}) === 'string' // false
https://codepen.io/patodiblasi/pen/NQXPwY?editors=0012
检查其他类型:
type(null) //null
type(undefined) //undefined
type([]) //array
type({}) //object
type(function() {}) //function
type(123) //number
type(new Number(123)) //number
type(/some_regex/) //regexp
type(Symbol("foo")) //symbol
【讨论】:
foo === null 或 typeof foo == "string"。否决票可能是因为 1. 这可能有点不习惯;尽管使用Object.prototype.toString 很常见,但我从未见过有人像您一样将类型从结果中提取出来,只与可能结果的确切值进行比较,例如"[object String]" 2。您没有解释正则表达式的作用或原因,对于 JavaScript 新手来说,这可能非常不清楚,并且 3. 不清楚为什么更喜欢这个而不是其他答案。
我发现这种简单的技术对于 String 的类型检查非常有用 -
String(x) === x // true, if x is a string
// false in every other case
const test = x =>
console.assert
( String(x) === x
, `not a string: ${x}`
)
test("some string")
test(123) // assertion failed
test(0) // assertion failed
test(/some regex/) // assertion failed
test([ 5, 6 ]) // assertion failed
test({ a: 1 }) // assertion failed
test(x => x + 1) // assertion failed
同样的技术也适用于 Number -
Number(x) === x // true, if x is a number
// false in every other case
const test = x =>
console.assert
( Number(x) === x
, `not a number: ${x}`
)
test("some string") // assertion failed
test(123)
test(0)
test(/some regex/) // assertion failed
test([ 5, 6 ]) // assertion failed
test({ a: 1 }) // assertion failed
test(x => x + 1) // assertion failed
对于 RegExp -
RegExp(x) === x // true, if x is a regexp
// false in every other case
const test = x =>
console.assert
( RegExp(x) === x
, `not a regexp: ${x}`
)
test("some string") // assertion failed
test(123) // assertion failed
test(0) // assertion failed
test(/some regex/)
test([ 5, 6 ]) // assertion failed
test({ a: 1 }) // assertion failed
test(x => x + 1) // assertion failed
对象也一样-
Object(x) === x // true, if x is an object
// false in every other case
注意,正则表达式、数组和函数也被视为对象。
const test = x =>
console.assert
( Object(x) === x
, `not an object: ${x}`
)
test("some string") // assertion failed
test(123) // assertion failed
test(0) // assertion failed
test(/some regex/)
test([ 5, 6 ])
test({ a: 1 })
test(x => x + 1)
但是,检查 Array 有点不同 -
Array.isArray(x) === x // true, if x is an array
// false in every other case
const test = x =>
console.assert
( Array.isArray(x)
, `not an array: ${x}`
)
test("some string") // assertion failed
test(123) // assertion failed
test(0) // assertion failed
test(/some regex/) // assertion failed
test([ 5, 6 ])
test({ a: 1 }) // assertion failed
test(x => x + 1) // assertion failed
这种技术不适用于函数但是 -
Function(x) === x // always false
【讨论】:
var x = new String(x); String(x)===x 返回 false。但是({}).toString.call(x).search(/String/)>0 总是返回字符串
function isClass(x,re){return ({}).toString.call(x).search(re)>0;}; isClass("hello",/String/) 或 isClass(3,/Number/) 或 isClass(null,/Null/)
new String(x) 应该 算作字符串并不明显。它是一个包装对象,具有与普通字符串不同的行为。除非您出于某种奇怪的原因对您希望您的检查如何处理字符串包装器对象有特定要求(您可能没有,因为首先没有理由使用它们),这并不是对这个答案的真正打击.
我还发现这也很好用,而且它比其他示例短很多。
if (myVar === myVar + '') {
//its string
} else {
//its something else
}
通过连接空引号,它会将值转换为字符串。如果myVar已经是一个字符串那么if语句就成功了。
【讨论】:
typeof 相比,这对我来说似乎有点贵。
typeof 慢了大约 20%,但仍然比 toString 快了不少。不管怎样,我想我只是喜欢强制的语法。
var s = new String('abc'); > s === s + '' > false
object 类型的new String cus。 w3schools.com/js/tryit.asp?filename=tryjs_string_object2
var a = new String('')
var b = ''
var c = []
function isString(x) {
return x !== null && x !== undefined && x.constructor === String
}
console.log(isString(a))
console.log(isString(b))
console.log(isString(c))
【讨论】:
false。
以下方法将检查任何变量是否为字符串(包括不存在的变量)。
const is_string = value => {
try {
return typeof value() === 'string';
} catch (error) {
return false;
}
};
let example = 'Hello, world!';
console.log(is_string(() => example)); // true
console.log(is_string(() => variable_doesnt_exist)); // false
【讨论】:
is_string(x) 告诉我x 是否是一个字符串,但它告诉我x 是否是一个返回 字符串的可调用对象。为什么我要传入一个函数而不是直接传递我的值?
is_string 函数用于检查变量是否存在并且是字符串。传递的箭头函数允许传递一个不存在的变量,而通常,如果变量不存在,我们会收到错误:“未捕获的 ReferenceError:变量未定义”。该用例类似于 PHP 中的错误控制运算符(即is_string(@$example))。这可能不是最佳或最常见的做法,但有人可能会觉得它很有用,这就是这个答案与众不同的原因。
这对我来说已经足够了。
警告:这不是一个完美的解决方案。 请参阅我的帖子底部。
Object.prototype.isString = function() { return false; };
String.prototype.isString = function() { return true; };
var isString = function(a) {
return (a !== null) && (a !== undefined) && a.isString();
};
你可以像下面这样使用它。
//return false
isString(null);
isString(void 0);
isString(-123);
isString(0);
isString(true);
isString(false);
isString([]);
isString({});
isString(function() {});
isString(0/0);
//return true
isString("");
isString(new String("ABC"));
警告:在这种情况下工作不正确:
//this is not a string
var obj = {
//but returns true lol
isString: function(){ return true; }
}
isString(obj) //should be false, but true
【讨论】:
一个简单的解决方案是:
var x = "hello"
if(x === x.toString()){
// it's a string
}else{
// it isn't
}
【讨论】:
toString()函数
.toString;尝试如果要检查的 x 为 null 或未定义,您的代码会抛出异常
toString() 方法可能被覆盖并且可能抛出异常(由于某些特定的实现),并且您的检查肯定不会起作用。主要思想是你不应该调用与你想要得到的东西无关的方法。我什至没有谈论与toString 方法相关的不必要开销。投反对票。
类型检查器助手:
function isFromType(variable, type){
if (typeof type == 'string') res = (typeof variable == type.toLowerCase())
else res = (variable.constructor == type)
return res
}
用法:
isFromType('cs', 'string') //true
isFromType('cs', String) //true
isFromType(['cs'], Array) //true
isFromType(['cs'], 'object') //false
另外,如果你希望它是递归的(比如数组是一个对象),你可以使用instanceof。
(['cs'] instanceof Object //true)
【讨论】:
我将在这里采用与其他方法不同的方法,它试图判断变量是特定类型还是特定集合的成员。
JS 是建立在鸭式的;如果某个东西像字符串一样嘎嘎作响,我们可以而且应该像字符串一样使用它。
7 是字符串吗?那为什么/\d/.test(7) 有效?{toString:()=>('hello there')} 是字符串吗?那为什么({toString:()=>('hello there')}) + '\ngeneral kenobi!' 有效?
这些不是关于应该上述工作的问题,重点是他们做到了。
所以我做了一个duckyString() function
下面我测试了许多其他答案没有解决的案例。对于每个代码:
duckyString() 以规范化需要真实字符串的代码的输入text = 'hello there';
out(text.replace(/e/g, 'E') + ' ' + 'hello there'.replace(/e/g, 'E'));
out('Is string? ' + duckyString(text) + '\t"' + duckyString(text, true) + '"\n');
text = new String('oh my');
out(text.toUpperCase() + ' ' + 'oh my'.toUpperCase());
out('Is string? ' + duckyString(text) + '\t"' + duckyString(text, true) + '"\n');
text = 368;
out((text + ' is a big number') + ' ' + ('368' + ' is a big number'));
out('Is string? ' + duckyString(text) + '\t"' + duckyString(text, true) + '"\n');
text = ['\uD83D', '\uDE07'];
out(text[1].charCodeAt(0) + ' ' + '?'[1].charCodeAt(0));
out('Is string? ' + duckyString(text) + '\t"' + duckyString(text, true) + '"\n');
function Text() { this.math = 7; }; Text.prototype = {toString:function() { return this.math + 3 + ''; }}
text = new Text();
out(String.prototype.match.call(text, '0') + ' ' + text.toString().match('0'));
out('Is string? ' + duckyString(text) + '\t"' + duckyString(text, true) + '"\n');
这与 !!x 与 x===true 不同,并且测试某些东西是否是数组类似,而不是需要一个实际的数组。
jQuery 对象;它们是数组吗?不,它们够好吗?是的,您可以通过 Array.prototype 函数运行它们就好了。
正是这种灵活性赋予了 JS 强大的功能,而测试 for 字符串会降低您的代码的互操作性。
上面的输出是:
hEllo thErE hEllo thErE
Is string? true "hello there"
OH MY OH MY
Is string? true "oh my"
368 is a big number 368 is a big number
Is string? true "368"
56839 56839
Is string? true "?"
0 0
Is string? true "10"
所以,这就是为什么你想知道某个东西是否是一个字符串。
如果像我一样,您从 google 来到这里并想看看是否有类似 字符串的,这里有一个答案。
除非您使用非常长或深度嵌套的 char 数组,否则它甚至都不贵。
这是因为它都是 if 语句,没有像 .toString() 这样的函数调用。
除非你试图查看一个 char 数组是否包含只有 toString() 或多字节字符的对象,在这种情况下,除了制作字符串并分别计算字节组成的字符之外,没有其他方法可以检查
function duckyString(string, normalise, unacceptable) {
var type = null;
if (!unacceptable)
unacceptable = {};
if (string && !unacceptable.chars && unacceptable.to == null)
unacceptable.to = string.toString == Array.prototype.toString;
if (string == null)
;
//tests if `string` just is a string
else if (
!unacceptable.is &&
(typeof string == 'string' || string instanceof String)
)
type = 'is';
//tests if `string + ''` or `/./.test(string)` is valid
else if (
!unacceptable.to &&
string.toString && typeof string.toString == 'function' && string.toString != Object.prototype.toString
)
type = 'to';
//tests if `[...string]` is valid
else if (
!unacceptable.chars &&
(string.length > 0 || string.length == 0)
) {
type = 'chars';
//for each char
for (var index = 0; type && index < string.length; ++index) {
var char = string[index];
//efficiently get its length
var length = ((duckyString(char, false, {to:true})) ?
char :
duckyString(char, true) || {}
).length;
if (length == 1)
continue;
//unicode surrogate-pair support
char = duckyString(char, true);
length = String.prototype[Symbol && Symbol.iterator];
if (!(length = length && length.call(char)) || length.next().done || !length.next().done)
type = null;
}
}
//return true or false if they dont want to auto-convert to real string
if (!(type && normalise))
//return truthy or falsy with <type>/null if they want why it's true
return (normalise == null) ? type != null : type;
//perform conversion
switch (type) {
case 'is':
return string;
case 'to':
return string.toString();
case 'chars':
return Array.from(string).join('');
}
}
包括选项
.toString())这里有更多测试,因为我是一个完成主义者:
out('Edge-case testing')
function test(text, options) {
var result = duckyString(text, false, options);
text = duckyString(text, true, options);
out(result + ' ' + ((result) ? '"' + text + '"' : text));
}
test('');
test(null);
test(undefined);
test(0);
test({length:0});
test({'0':'!', length:'1'});
test({});
test(window);
test(false);
test(['hi']);
test(['\uD83D\uDE07']);
test([['1'], 2, new String(3)]);
test([['1'], 2, new String(3)], {chars:true});
输出:
Edge-case testing
is ""
null null
null null
to "0"
chars ""
chars "!"
null null
chars ""
to "false"
null null
chars "?"
chars "123"
to "1,2,3"
【讨论】:
只是为了扩展@DRAX 的answer,我会这样做:
function isWhitespaceEmptyString(str)
{
//RETURN:
// = 'true' if 'str' is empty string, null, undefined, or consists of white-spaces only
return str ? !(/\S/.test(str)) : (str === "" || str === null || str === undefined);
}
它还将考虑nulls 和undefined 类型,它会处理非字符串类型,例如0。
【讨论】:
只有字符串没有数字的代码
isNaN("A") = true;
parseInt("A") = NaN;
isNaN(NaN) = true;
我们可以使用 isNaN(parseInt()) 只有字符串
let ignoreNumbers = "ad123a4m";
let ign = ignoreNumbers.split("").map((ele) => isNaN(parseInt(ele)) ? ele : "").join("");
console.log(ign);
【讨论】:
从lodash库实现v4.0.0
// getTag.js
const toString = Object.prototype.toString;
/**
* Gets the `toStringTag` of `value`.
*
* @private
* @param {*} value The value to query.
* @returns {string} Returns the `toStringTag`.
*/
function getTag(value) {
if (value == null) {
return value === undefined
? "[object Undefined]"
: "[object Null]";
}
return toString.call(value);
}
// isString.js
import getTag from "./getTag.js";
/**
* Checks if `value` is classified as a `String` primitive or object.
*
* @since 0.1.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a string, else `false`.
* @example
*
* isString('abc')
* // => true
*
* isString(1)
* // => false
*/
function isString(value) {
const type = typeof value;
return (
type === "string" || (type === "object" &&
value != null &&
!Array.isArray(value) &&
getTag(value) == "[object String]")
);
}
export default isString;
【讨论】:
我不确定你的意思是知道它是否是 string 类型,无论其内容如何,或者它的内容是数字还是字符串,无论其类型如何。
所以要知道它的类型是否是一个字符串,这已经得到了回答。
但是要根据它的内容知道它是一个字符串还是一个数字,我会使用这个:
function isNumber(item) {
return (parseInt(item) + '') === item;
}
还有一些例子:
isNumber(123); //true
isNumber('123'); //true
isNumber('123a');//false
isNumber(''); //false
【讨论】:
/^\d+$/.test('123') 来避免潜在解析问题的复杂性)