Відповіді:
Ви можете скористатися 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"
Приклад з цієї веб-сторінки . (Приклад був дещо змінений).
Це не буде працювати, як очікувалося, у випадку з рядками, створеними з new String()
, але це рідко використовується та рекомендується проти [1] [2] . Дивіться інші відповіді, як впоратися з ними, якщо ви цього хочете.
new String('foo')
, але це не має значення, тому що об'єктировані рядки - це нікчемна функція, яку ви не повинні використовувати. Посібник зі стилів Google забороняє їм , Дуглас Крокфорд хоче, щоб вони застаріли , і жодна бібліотека їх не використовує. Притворіться, що їх не існує, і використовуйте typeof
без побоювання.
Ось що для мене працює:
if (typeof myVar === 'string' || myVar instanceof String)
// it's a string
else
// it's something else
instanceof
перевірка тут - безглуздий шум, якщо ви не дотримуєтесь дуже незвичних методів кодування, і ця відповідь нічого не пояснює, що він робить, або для чого ви можете ним користуватися. Єдина причина, яка вам коли-небудь знадобиться, це те, що ви використовуєте об'єкти, обернені рядками, але обернені об'єктами рядки - це нікчемна функція, яку ніхто не використовує, а Google і Crockford обидва засуджують як погану практику ( google-styleguide.googlecode.com/svn/ багажник /… , crockford.com/javascript/recommend.html ).
typeof
і вам instanceof
здається гарною порадою, якщо ваш код можуть називати інші. @ Крайній postmessage
випадок MarkAmery має значення, якщо ви запитуєте "що я щойно робив postmessage
?" - але ви очікуєте, що обробляти їх через інтерфейс і не дозволяти поширюватись. В іншому випадку видається правильним поводитися з непридатними методами кодування, навіть якщо деякі JS-естети їх не схвалюють. НІКОЛИ не коментуйте свій код як такий, що приймає String, якщо це не справді!
Оскільки 580+ людей проголосували за неправильну відповідь, а 800+ проголосували за працюючу, але відповідь у стилі рушниці, я подумав, що варто було б повторити свою відповідь у більш простій формі, яку кожен може зрозуміти.
function isString(x) {
return Object.prototype.toString.call(x) === "[object String]"
}
Або вбудований (у мене є налаштування UltiSnip для цього):
Object.prototype.toString.call(myVar) === "[object String]"
FYI, відповідь Пабло Санта-Крус неправильна, тому що typeof new String("string")
єobject
Відповідь DRAX точна і функціональна, і вона повинна бути правильною відповіддю (оскільки Пабло Санта Крус, безумовно, невірний, і я не буду сперечатися проти народного голосування.)
Однак ця відповідь також безумовно правильна і насправді найкраща відповідь (за винятком, можливо, пропозиції щодо використання лодашу / підкреслення ). відмова від відповідальності: Я взяв внесок у кодову базу 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
але це був би поганий підхід до вирішення проблеми, якої ви не повинні мати в першу чергу).
myObject+"" === myObject
чи є об'єктом рядок (або ще краще, я б не вводив перевірку в системі типу поведінки, керованої в першу чергу).
toString
в Object.prototype
. Отже, я б стверджував, що покладатися на 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
Докладніше див. Документація lodash для _.isString () для отримання більш детальної інформації.
Докладніше див. У документації jQuery для $ .type () .
_.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]'
?
(x === y)
кращу читаність ніж x === y
?
Кращий спосіб:
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 ()" тощо.
Також Duck-Typing: "Якщо вона схожа на качку, ходить як качка, і пахне качкою - це має бути масив". Значить, перевірте її властивості.
Сподіваюсь, це допомагає.
Пам'ятайте, ви завжди можете використовувати і комбінації підходів. Ось приклад використання вбудованої карти дій з typeof :
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 - / - mapping mapping" - для з'ясування, чи змінна насправді "існує". Тепер ви можете розділити це неприємне волосся між null
& 0
!
Багато разів ви навіть не переймаєтесь його типом . Ще один спосіб обійти тип введення - це поєднання наборів типу Duck:
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
. Ви просто переконалися, що рядковий еквівалент числа був однаковим, і потім ви переконалися, що перевели його у http
функцію як Number
. Іншими словами, нас навіть не хвилювало, що це за тип.
Сподіваюся, що вам більше допоможе працювати :)
(o.constructor === Number || s.constructor === Boolean)
). Цікаво, parseInt
і NaN
тендітні , але потужні інструменти. Пам'ятайте лише, що "Не-число" НЕ є "Не-числом", і його можна визначити невизначеним.
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'));
Мені подобається використовувати це просте рішення:
var myString = "test";
if(myString.constructor === String)
{
//It's a string
}
undefined
і null
, і все-таки отримати відповідь правильно для порожніх рядків (і те й інше)''
та new String('')
).
(mystring || false) && mystring.constructor === String
. Я використовував false, якщо він використовується у функції, яка повинна повернути булеву форму.
Це чудовий приклад того, чому продуктивність має значення:
Зробити щось таке просте, як тест для рядка, може бути дорого, якщо зробити це не правильно.
Наприклад, якщо я хотів написати функцію для перевірки, чи є щось рядок, я міг би це зробити одним із двох способів:
1) const isString = str => (Object.prototype.toString.call(str) === '[object String]');
2) const isString = str => ((typeof str === 'string') || (str instanceof String));
І те й інше досить прямо, тому що може вплинути на продуктивність? Взагалі кажучи, функціональні дзвінки можуть бути дорогими, особливо якщо ви не знаєте, що відбувається всередині. У першому прикладі є виклик функції методу toString Object. У другому прикладі викликів функцій немає, оскільки typeof та instanceof є операторами. Оператори значно швидше, ніж функціональні дзвінки.
Коли тестується продуктивність, приклад 1 на 79% повільніше, ніж приклад 2!
Дивіться тести: https://jsperf.com/isstringtype
typeof str === 'string' || str instanceof String
(може скидати дужки, які я віддаю перевагу у if (..)
випадках); незважаючи на те, що перевірка як примітивних, так і об'єктних типів у №2 є зрозумілою та достатньою. Ці перевірки в будь-якому випадку повинні бути "рідкісними".
if (s && typeof s.valueOf() === "string") {
// s is a string
}
Працює як для рядкових літералів, так let s = 'blah'
і для об'єктних рядківlet s = new String('blah')
Взято з лодаша:
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
Я думаю, що рішення @customcommander повинно вистачити в 90% ваших випадків:
typeof str === 'string'
Має служити вам правильно (просто оскільки зазвичай new String('something')
у вашому коді немає причин ).
Якщо вам цікаво поводитися з цим String
об'єкта (наприклад, ви очікуєте, що якийсь вар від третьої сторони), то використання lodash, як запропонував @ ClearCloud8, здається чітким, простим та елегантним рішенням.
Однак я б запропонував бути обережними з такими бібліотеками, як лодаш, через їх розмір. Замість того, щоб робити
import _ from 'lodash'
...
_.isString(myVar)
Що приносить весь величезний об'єкт лодашу, я б запропонував щось подібне:
import { isString as _isString } from 'lodash'
...
_isString(myVar)
І з простим пакетом ви повинні бути добре (тут я посилаюся на код клієнта).
Якщо ви працюєте в середовищі node.js, ви можете просто використовувати вбудовану функцію isString в утилітах.
const util = require('util');
if (util.isString(myVar)) {}
Редагувати: як згадував @Jehy, це припинено з моменту v4.
typeof value === 'string'
Замість цього використовувати ".
x = new String('x'); x.isString(x);
повертає помилкове . Існує, util.types.isStringObject()
але це повертає значення false для x = 'x'
рядка типу. Дві функції утиліти, які абсолютно не надають корисності ...
Наступний метод перевірить, чи є якась змінна рядок ( включаючи змінні, які не існують ).
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
Я також виявив, що це теж добре працює, і це набагато коротше, ніж інші приклади.
if (myVar === myVar + '') {
//its string
} else {
//its something else
}
Шляхом об'єднання на порожні лапки перетворює значення в рядок. Якщо myVar
вже є рядок, то оператор if успішний.
typeof
.
typeof
але все ще зовсім трохи швидше, ніж toString
. У будь-якому випадку, я думаю, мені просто подобається синтаксис примусу.
var s = new String('abc'); > s === s + '' > false
new String
CUS, який створює тип object
. 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
.
Я вважаю цю просту техніку корисною для перевірки типу 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
повертає помилкове. проте ({}).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/)
Простим рішенням буде:
var x = "hello"
if(x === x.toString()){
// it's a string
}else{
// it isn't
}
toString()
функцію
.toString
жодні значення; спробуйте, якщо х для перевірки є недійсним або невизначеним, виняток для вашого викидання коду
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()
функцію.
Нижче я перевіряю багато випадків, на які не відповідають інші відповіді. Для кожного коду:
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 свою силу, і тестування на рядків спеціально робить код менш сумісним.
Вихід із зазначеного вище:
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.
Це тому, що це все, якщо оператори, а не виклики функції .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 в відповідь , я б це зробити:
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);
}
Він буде враховувати також null
s та undefined
типи, і він буде піклуватися про нерядкові типи, такі як 0
.
Це досить добре для мене.
УВАГА: Це не ідеальне рішення. Дивіться внизу моєї публікації.
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 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
Я не впевнений, якщо ви хочете знати, чи це тип string
незалежно від його вмісту, чи це вміст - це число чи рядок, незалежно від його типу.
Отже, щоб знати, чи є його тип рядка, на це вже відповіли.
Але, щоб знати на основі його вмісту, якщо це рядок або число, я б використав це:
function isNumber(item) {
return (parseInt(item) + '') === item;
}
І для деяких прикладів:
isNumber(123); //true
isNumber('123'); //true
isNumber('123a');//false
isNumber(''); //false
/^\d+$/.test('123')
щоб уникнути тонкощів потенційних проблем розбору)