Перевірте, чи є змінною рядок у JavaScript


1737

Як я можу визначити, чи змінна - це рядок чи щось інше в JavaScript?

Відповіді:


1689

Ви можете скористатися 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] . Дивіться інші відповіді, як впоратися з ними, якщо ви цього хочете.


  1. Посібник зі стилю Google JavaScript говорить, що ніколи не використовувати обгортки примітивних об'єктів .
  2. Дуглас Крокфорд рекомендував припиняти обгортання примітивних предметів .

45
@ Wolfy87 Зауважте, що є деякі випадки, коли typeof stringValue може повернути "об'єкт" замість "string". Дивіться коментарі до моєї відповіді.
ДРАКС

163
Моя бажана відповідь. Аргумент проти цього полягає в тому, що він "не працює" для об'єктів, обернутих на зразок new String('foo'), але це не має значення, тому що об'єктировані рядки - це нікчемна функція, яку ви не повинні використовувати. Посібник зі стилів Google забороняє їм , Дуглас Крокфорд хоче, щоб вони застаріли , і жодна бібліотека їх не використовує. Притворіться, що їх не існує, і використовуйте typeofбез побоювання.
Марк Амері


2
@DanielLe, тому що він запропонував заміну, яка виправляє деякі проблеми, а не тому, що він в принципі проти.
Всеволод Голованов

4
Якщо це заподіює вам головний біль, 99,99% часу, це тому, що ви не правильно сформулювали код. Це не провина NaN у тому, що існує, і робити те, що робить, це те, що вам слід врахувати, вивчити та пам’ятати про наступний раз, коли ви працюєте з кодом, який може його отримати.
Майк 'Помакс' Камерманс

1905

Ось що для мене працює:

if (typeof myVar === 'string' || myVar instanceof String)
// it's a string
else
// it's something else

77
Чи "myVar instanceof String" робить щось вище "та" поза "typeof myVar == 'string" "?
svth

81
@svth я згадав. У JavaScript ви можете мати змінний тип рядка або тип об'єкта, який є класом String (те саме - обидва - це рядки - але визначено по-різному), тому двічі перевіряється.
DRAX

38
var somevar = new String ('somestring') console.log (typeof somevar) // об’єкт
Danubian Sailor

82
-1 тому, що instanceofперевірка тут - безглуздий шум, якщо ви не дотримуєтесь дуже незвичних методів кодування, і ця відповідь нічого не пояснює, що він робить, або для чого ви можете ним користуватися. Єдина причина, яка вам коли-небудь знадобиться, це те, що ви використовуєте об'єкти, обернені рядками, але обернені об'єктами рядки - це нікчемна функція, яку ніхто не використовує, а Google і Crockford обидва засуджують як погану практику ( google-styleguide.googlecode.com/svn/ багажник /… , crockford.com/javascript/recommend.html ).
Марк Амерді

78
Я рішуче не погоджуюся, що писати твердий код, який правильно розглядає малоймовірні випадки, є чогось уникнути. Перевірка обох typeofі вам instanceofздається гарною порадою, якщо ваш код можуть називати інші. @ Крайній postmessageвипадок MarkAmery має значення, якщо ви запитуєте "що я щойно робив postmessage?" - але ви очікуєте, що обробляти їх через інтерфейс і не дозволяти поширюватись. В іншому випадку видається правильним поводитися з непридатними методами кодування, навіть якщо деякі JS-естети їх не схвалюють. НІКОЛИ не коментуйте свій код як такий, що приймає String, якщо це не справді!
Деві Морган

157

Оскільки 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))


11
Ви рекомендуєте underscore.js (з якої дивної причини?), Але ви не використовуєте його тут. Крім того, ви забруднюєте глобальний простір імен функціями. У node.js ви створили б модуль, який би мав усі ці функції (ви можете використовувати їх global || windowзамість, windowале це був би поганий підхід до вирішення проблеми, якої ви не повинні мати в першу чергу).
Бенджамін Груенбаум

19
@BenjaminGruenbaum Я прийшов шукати відповідь на питання ОП, і жодна з відповідей мені не сподобалась. Тож я перевірив, що робиться підкресленням, і подумав, що достатньо витончено, щоб витягнути та змінити трохи (щоб уникнути завантаження бібліотеки підкреслення). Я уточню свою посаду.
Орвелофіл

2
@Orwellophile Класно, я розумію, ваша оригінальна відповідь була сформульована так, як ви пропонуєте сам підкреслити. Особисто я просто перевіряю, myObject+"" === myObjectчи є об'єктом рядок (або ще краще, я б не вводив перевірку в системі типу поведінки, керованої в першу чергу).
Бенджамін Груенбаум

18
@ Орвелофіл, як це краще, ніж відповідь DRAX?
Pacerier

3
JS підтримує виправлення мавп, так що можна повторно визначити toStringв Object.prototype. Отже, я б стверджував, що покладатися на toStringперевірку типу об’єкта - це, у кращому випадку, погана практика.
Андре Родрігес

84

Я рекомендую використовувати вбудовані функції з 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 () .


96
Це головне, що не так із спільнотою JS - перевірка проти примітивного типу є одноланковою і передбачає побудову мови (одна з основних), але ви рекомендуєте використовувати зовнішню бібліотеку. Якщо хтось уже використовує одну з цих бібліотек, це може бути хорошою ідеєю, але завантажувати їх лише для цього, а не просто перевіряти тип - це надлишок.
Rafał Wrzeszcz

5
Я збираюся погодитися з Рафалом. Я всюди бачу, що це покращує "читабельність" використання однієї з цих зовнішніх бібліотек. Якщо ви знаєте JavaScript, то читати його простіше, ніж якусь зовнішню бібліотеку, яку ви не використовували. _.every()спочатку трохи заплутано, і щось таке просте, як _.isBoolean()заплутало розробників у моїй компанії. Дев помилково подумав, що було б помилковим, якщо значення було булевим і хибним. Англійську для мене легше читати, ніж німецьку, тому що я не знаю німецької. Вивчіть JavaScript, і все це матиме сенс.
Джон Гардінг

20
@ RafałWrzeszcz Ці бібліотеки досить широко використовуються і надають багато корисної (і перевіреної) функціональності. Особливо лодаш. Я б не рекомендував комусь завантажувати бібліотеку лише для використання для цього одного рішення .... але я б рекомендував кожному розробнику JavaScript завантажити цю бібліотеку і подивитися, на що вони відсутні. ;)
ClearCloud8

13
Всім вам не вистачає точки бібліотеки, як Лодаш: не швидкість. Не "простота розвитку". Причина використовувати таку бібліотеку, як Лодаш, забезпечує «захисність» проти проблем, які підірвуть ваш додаток js. Фатальні помилки трапляються при спробі робити рядкові операції на об'єкті (або навпаки), і Лодаш надає величезну цінність щодо запобігання цих помилок.
random_user_name

1
Майте на увазі, що багато людей будуть робити це в середовищі Вузла або Вузла, і мало хто буде використовувати jQuery там.
Метт Флетчер

35
function isString (obj) {
  return (Object.prototype.toString.call(obj) === '[object String]');
}

Я це побачив тут:

http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/


4
Я вважаю, що це рішення є найбільш надійним, оскільки воно обробляє еталонні сценарії між рамками / перехресними вікнами, як зазначено в URL-адресі, наданій у відповіді.
ewh

1
Чудова відповідь, схоже, що Underscore.js також використовує цей метод!
Даан

1
@ling Просто цікаво, чому ти ставиш круглі дужки Object.prototype.toString.call(obj) === '[object String]'?
StubbornShowaGuy

@Earlee Ви маєте на увазі (x === y)кращу читаність ніж x === y?
StubbornShowaGuy

@StubbornShowaGuy На мою думку, так. Йдеться також про послідовність. Я особисто використовую дужки при поверненні значення.
Акварель

28

Кращий спосіб:

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: "Якщо вона схожа на качку, ходить як качка, і пахне качкою - це має бути масив". Значить, перевірте її властивості.

Сподіваюсь, це допомагає.

Редагувати; 05.12.2016

Пам'ятайте, ви завжди можете використовувати і комбінації підходів. Ось приклад використання вбудованої карти дій з 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. Іншими словами, нас навіть не хвилювало, що це за тип.

Сподіваюся, що вам більше допоможе працювати :)


Вам знадобиться інша перевірка на звичайні старі номери, оскільки спроба взяти їх властивість конструктора не вдасться:

@torazaburo Для мене нормально працював лише зараз на консолі Chrome. Чому ви думаєте, що це не спрацює?
Марк Амері

2
@torazaburo Ви можете пограти з твердженнями ( (o.constructor === Number || s.constructor === Boolean)). Цікаво, parseIntі NaNтендітні , але потужні інструменти. Пам'ятайте лише, що "Не-число" НЕ є "Не-числом", і його можна визначити невизначеним.
Коді

1
a.constructor === Масив помиляється і може вийти з ладу іноді, скористайтеся Array.isArray, див. web.mit.edu/jwalden/www/isArray.html
axkibe

1
Погоджено, це не є безпечним. Кращим способом є використання перевірок власності - це єдиний справді безпечний спосіб відмови. Приклад: if(thing.call) { 'its a function'; }або if(thing.defineProperties) { 'its an object'; }. Дякую за вклад, axkibe!
Коді

17

Я не можу чесно зрозуміти, чому б не просто використовувати 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'));


15

Мені подобається використовувати це просте рішення:

var myString = "test";
if(myString.constructor === String)
{
     //It's a string
}

3
Чим це відрізняється від відповіді Коді через 4 роки?
Джонатан Н

3
Відповідь @Sheljohn Cody чудова. Моя відповідь (повний текст) коротша і прямо до суті. Ви запитали ... :)
ScottyG

Як функція, для цього знадобиться спосіб розібратися undefinedі null, і все-таки отримати відповідь правильно для порожніх рядків (і те й інше)'' та new String('')).
MikeBeaton

@MikeBeaton Немає проблем: (mystring || false) && mystring.constructor === String. Я використовував false, якщо він використовується у функції, яка повинна повернути булеву форму.
алани

13

Це чудовий приклад того, чому продуктивність має значення:

Зробити щось таке просте, як тест для рядка, може бути дорого, якщо зробити це не правильно.

Наприклад, якщо я хотів написати функцію для перевірки, чи є щось рядок, я міг би це зробити одним із двох способів:

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 є зрозумілою та достатньою. Ці перевірки в будь-якому випадку повинні бути "рідкісними".
користувач2864740

12
if (s && typeof s.valueOf() === "string") {
  // s is a string
}

Працює як для рядкових літералів, так let s = 'blah'і для об'єктних рядківlet s = new String('blah')


3
Увага! Це не вдасться на порожніх рядках, оскільки це фальси.
Філіп Сумі


5

Я думаю, що рішення @customcommander повинно вистачити в 90% ваших випадків:

typeof str === 'string'

Має служити вам правильно (просто оскільки зазвичай new String('something')у вашому коді немає причин ).

Якщо вам цікаво поводитися з цим String об'єкта (наприклад, ви очікуєте, що якийсь вар від третьої сторони), то використання lodash, як запропонував @ ClearCloud8, здається чітким, простим та елегантним рішенням.

Однак я б запропонував бути обережними з такими бібліотеками, як лодаш, через їх розмір. Замість того, щоб робити

import _ from 'lodash'
...
_.isString(myVar)

Що приносить весь величезний об'єкт лодашу, я б запропонував щось подібне:

import { isString as _isString } from 'lodash'
...
_isString(myVar)

І з простим пакетом ви повинні бути добре (тут я посилаюся на код клієнта).


чому === коли == достатньо
завершити

4

Якщо ви працюєте в середовищі node.js, ви можете просто використовувати вбудовану функцію isString в утилітах.

const util = require('util');
if (util.isString(myVar)) {}

Редагувати: як згадував @Jehy, це припинено з моменту v4.


Чи є заміна?
Ентоні Конг

3
Документи кажуть " typeof value === 'string'Замість цього використовувати ".
Містер Роджерс

x = new String('x'); x.isString(x);повертає помилкове . Існує, util.types.isStringObject()але це повертає значення false для x = 'x'рядка типу. Дві функції утиліти, які абсолютно не надають корисності ...
спінку

4

Наступний метод перевірить, чи є якась змінна рядок ( включаючи змінні, які не існують ).

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

3

Я також виявив, що це теж добре працює, і це набагато коротше, ніж інші приклади.

if (myVar === myVar + '') {
   //its string
} else {
   //its something else
}

Шляхом об'єднання на порожні лапки перетворює значення в рядок. Якщо myVarвже є рядок, то оператор if успішний.


3
Єдина проблема полягає в тому, що ви примушуєте змінну, коли хочете перевірити її тип. Це здається мені трохи дорогим у порівнянні з typeof.
Оличний

1
Так що, ви праві. jsperf сказав, що це було на 20% повільніше, typeofале все ще зовсім трохи швидше, ніж toString. У будь-якому випадку, я думаю, мені просто подобається синтаксис примусу.
Кріс Дельфін

4
це не працює з типом String; var s = new String('abc'); > s === s + '' > false
user5672998

1
Не працює з new StringCUS, який створює тип object. w3schools.com/js/tryit.asp?filename=tryjs_string_object2
Кріс Дельфін

Добре продумано, але залишає поза краєм корпус об'єктів, обвитих струнами.
Ентоні Рутлідж

3
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))

Чому вам потрібно перевірити на null або undefined, якщо x.constructor === String також поверне значення false для null або undefined?
Жуль Менсон

1
@JulesManson: Це призведе до помилки, а не до результатів false.
Ри-

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повертає помилкове. проте ({}).toString.call(x).search(/String/)>0завжди повертається за важкі речі
несинхронізований

1
function isClass(x,re){return ({}).toString.call(x).search(re)>0;}; isClass("hello",/String/) або isClass(3,/Number/)абоisClass(null,/Null/)
несинхронізований

2

Простим рішенням буде:

var x = "hello"

if(x === x.toString()){
// it's a string 
}else{
// it isn't
}

1
це не перевіряє, чи це рядок. Він перетворюється на рядок, багато речей мають toString()функцію
Мухаммед Умер

7
@MuhammadUmer Так, він перетворює його в рядок, але потім перевіряє ідентичність на вихідне значення, яке буде істинним, лише якщо початкове значення також є рядком.
MrWhite

4
це неправильно: ви не можете сліпо закликати .toStringжодні значення; спробуйте, якщо х для перевірки є недійсним або невизначеним, виняток для вашого викидання коду
user5672998

1
Ідея досі корисна. x === Рядок (x) безпечний і працює.
Márton

Дійсно? Це рішення здається мені занадто дивним, оскільки toString()метод може бути переосмислений і може викинути виняток (через певну реалізацію), і ваша перевірка не буде працювати точно. Основна ідея полягає в тому, що не слід називати методи, не пов'язані з тим, що ви хочете отримати. Я навіть не кажу про зайві накладні витрати, пов'язані з toStringметодом. Схильність
Рустем Зіннатуллін

2

Помічник шпильки:

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)


2

Я збираюся піти іншим маршрутом до решти тут, які намагаються сказати, чи є змінна певним типом чи членом певного набору.
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});
  • Всі негативні випадки, здається, враховуються
  • Це має працювати в браузерах> = IE8
  • Масиви Char із декількома байтами, що підтримуються в браузерах із підтримкою ітератора рядків

Вихід:

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"

1

Просто щоб розширити @ 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);
}

Він буде враховувати також nulls та undefinedтипи, і він буде піклуватися про нерядкові типи, такі як 0.


1

Це досить добре для мене.

УВАГА: Це не ідеальне рішення. Дивіться внизу моєї публікації.

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

-1

Ви можете використовувати цю функцію для визначення типу будь-якого:

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


-2

Я не впевнений, якщо ви хочете знати, чи це тип stringнезалежно від його вмісту, чи це вміст - це число чи рядок, незалежно від його типу.

Отже, щоб знати, чи є його тип рядка, на це вже відповіли.
Але, щоб знати на основі його вмісту, якщо це рядок або число, я б використав це:

function isNumber(item) {
    return (parseInt(item) + '') === item;
}

І для деяких прикладів:

isNumber(123);   //true
isNumber('123'); //true
isNumber('123a');//false
isNumber('');    //false

Я думаю, що спочатку я питав, як перевірити тип, хоча тоді я не знав, як навіть сформувати питання. (і я, мабуть, просто зробив це, /^\d+$/.test('123')щоб уникнути тонкощів потенційних проблем розбору)
Olical
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.