Kiểm tra xem một biến có phải là một chuỗi trong JavaScript không


1742

Làm cách nào để xác định xem một biến là một chuỗi hay thứ gì khác trong JavaScript?

Câu trả lời:


1692

Bạn có thể sử dụng typeoftoán tử:

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"

Ví dụ từ trang web này . (Ví dụ đã được sửa đổi một chút).

Điều này sẽ không hoạt động như mong đợi trong trường hợp các chuỗi được tạo bằng new String(), nhưng điều này hiếm khi được sử dụng và được đề xuất đối với [1] [2] . Xem các câu trả lời khác để biết cách xử lý những điều này, nếu bạn rất mong muốn.


  1. Hướng dẫn Phong cách Google JavaScript nói không bao giờ sử dụng trình bao bọc đối tượng nguyên thủy .
  2. Douglas Crockford khuyến nghị các trình bao bọc đối tượng nguyên thủy không được chấp nhận .

45
@ Wolfy87 Xin lưu ý rằng có một số trường hợp typeof stringValue có thể trả về "đối tượng" thay vì "chuỗi". Xem ý kiến ​​về câu trả lời của tôi.
DRAX

163
Câu trả lời ưa thích của tôi. Lập luận chống lại điều đó là 'thất bại' đối với các chuỗi được bọc đối tượng như thế new String('foo'), nhưng điều đó không quan trọng bởi vì các chuỗi được bọc đối tượng là một tính năng vô giá trị mà bạn không nên sử dụng. Hướng dẫn về phong cách Google cấm họ , Douglas Crockford muốn họ không được chấp nhận và không có thư viện nào sử dụng chúng. Giả vờ rằng chúng không tồn tại và sử dụng typeofmà không sợ hãi.
Đánh dấu Amery


2
@DanielLe, bởi vì anh ấy đề xuất một sự thay thế khắc phục một số vấn đề, chứ không phải vì anh ấy chống lại nguyên tắc đó.
Vsevolod Golovanov

4
Nếu nó khiến bạn đau đầu, 99,99% thời gian là do bạn không cấu trúc mã chính xác. Đó không phải là lỗi của NaN vì đã tồn tại và làm những gì nó làm, đó là điều bạn nên lưu ý, học hỏi và ghi nhớ vào lần tới khi bạn làm việc với mã có thể mang lại nó.
Mike 'Pomax' Kamermans

1909

Đây là những gì làm việc cho tôi:

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

77
"MyVar instanceof String" có làm gì ở trên và ngoài "typeof myVar == 'string'" không?
svth

81
@svth Tôi nhớ. Trong JavaScript, bạn có thể có loại chuỗi hoặc loại đối tượng là lớp Chuỗi (cùng một thứ - cả hai đều là chuỗi - nhưng được định nghĩa khác nhau) đó là lý do tại sao được kiểm tra hai lần.
DRAX

38
var somevar = new String ('somestring') console.log (typeof somevar) // object
Danubian Sailor

82
-1 vì instanceofkiểm tra ở đây là tiếng ồn vô nghĩa trừ khi bạn tuân theo một số thực tiễn mã hóa rất bất thường và câu trả lời này không có gì để giải thích nó làm gì hoặc tại sao bạn có thể sử dụng nó. Lý do duy nhất bạn cần là nếu bạn sử dụng các chuỗi được bọc đối tượng, nhưng các chuỗi được bọc đối tượng là một tính năng không có giá trị mà không ai sử dụng và cả Google và Crockford đều lên án là thông lệ xấu ( google-styleguide.googlecode.com/svn/ thân cây / khác , crockford.com/javascript/recommend.html ).
Đánh dấu Amery

79
Tôi rất không đồng ý rằng việc viết mã vững chắc xử lý chính xác các trường hợp không thể xảy ra là điều cần tránh. Kiểm tra cả hai typeofinstanceofcảm thấy như lời khuyên tốt nếu mã của bạn có thể được gọi bởi người khác. postmessageTrường hợp cạnh của @ MarkAmery có vấn đề nếu bạn hỏi "tôi vừa mới làm postmessagegì?" - nhưng bạn hy vọng rằng sẽ được xử lý tại giao diện và không được phép tuyên truyền. Ở những nơi khác, có vẻ đúng khi xử lý các phương thức mã hóa không bị phản đối ngay cả khi một số mỹ nhân JS không chấp nhận chúng. KHÔNG BAO GIỜ nhận xét mã của bạn là chấp nhận Chuỗi, trừ khi nó thực sự làm như vậy!
Dewi Morgan

157

Vì hơn 580 người đã bỏ phiếu cho một câu trả lời không chính xác và hơn 800 người đã bỏ phiếu cho một câu trả lời theo kiểu shotgun hoạt động, tôi nghĩ rằng nó có thể đáng để làm lại câu trả lời của tôi ở dạng đơn giản hơn mà mọi người có thể hiểu.

function isString(x) {
  return Object.prototype.toString.call(x) === "[object String]"
}

Hoặc, nội tuyến (Tôi có thiết lập UltiSnip cho việc này):

Object.prototype.toString.call(myVar) === "[object String]"

FYI, câu trả lời Pablo Santa Cruz là sai, vì typeof new String("string")object

Câu trả lời của DRAX là chính xác và đầy đủ chức năng, và phải là câu trả lời chính xác (vì Pablo Santa Cruz chắc chắn là không chính xác và tôi sẽ không tranh luận về việc bỏ phiếu phổ biến.)

Tuy nhiên, câu trả lời này cũng hoàn toàn chính xác và thực sự là câu trả lời tốt nhất (ngoại trừ, có lẽ, đối với gợi ý sử dụng lodash / gạch dưới ). từ chối trách nhiệm: Tôi đã đóng góp cho lodash 4 codebase.

Câu trả lời ban đầu của tôi (rõ ràng đã bay qua rất nhiều đầu) sau:

Tôi đã chuyển mã này từ underscore.js:

['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'].forEach( 
    function(name) { 
        window['is' + name] = function(obj) {
              return toString.call(obj) == '[object ' + name + ']';
    }; 
});

Điều đó sẽ xác định isString, isNumber, v.v.


Trong Node.js, điều này có thể được triển khai dưới dạng một mô-đun:

module.exports = [
  'Arguments',
  'Function', 
  'String', 
  'Number', 
  'Date', 
  'RegExp'
].reduce( (obj, name) => {
  obj[ 'is' + name ] = x => toString.call(x) == '[object ' + name + ']';
  return obj;
}, {});

[sửa]: cũng Object.prototype.toString.call(x)hoạt động để phân định giữa các chức năng và chức năng không đồng bộ:

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
Bạn đề xuất underscore.js (vì lý do kỳ quặc nào?) Nhưng bạn không sử dụng nó ở đây. Hơn nữa, bạn gây ô nhiễm không gian tên toàn cầu với các chức năng. Trong node.js, bạn sẽ tạo một mô-đun có tất cả các chức năng này (bạn có thể sử dụng global || windowthay thế windownhưng đó sẽ là một cách tiếp cận tồi để giải quyết vấn đề bạn không nên gặp ở nơi đầu tiên).
Benjamin Gruenbaum

19
@BenjaminGruenbaum Tôi đến tìm câu trả lời cho câu hỏi của OP và không thích bất kỳ câu trả lời nào. Vì vậy, tôi đã kiểm tra những gì gạch dưới đã làm, và nghĩ rằng nó đủ tiện lợi để trích xuất và sửa đổi một chút (để tránh phải tải thư viện gạch dưới). Tôi sẽ làm rõ bài viết của tôi.
Orwellophile

2
@Orwellophile Thật tuyệt, tôi hiểu rồi, câu trả lời ban đầu của bạn được đặt ra giống như bạn đang đề xuất gạch dưới. Cá nhân tôi chỉ cần kiểm myObject+"" === myObjecttra xem một đối tượng có phải là một chuỗi không (hoặc thậm chí tốt hơn, tôi sẽ không gõ kiểm tra trong một hệ thống loại điều khiển hành vi ở vị trí đầu tiên).
Benjamin Gruenbaum

18
@Orwellophile, Làm thế nào điều này tốt hơn câu trả lời của DRAX?
Pacerier

3
JS hỗ trợ vá khỉ, vì vậy có thể định nghĩa lại toStringtrong Object.prototype. Vì vậy, tôi cho rằng việc dựa vào toStringđể kiểm tra loại đối tượng, tốt nhất là, một thực tiễn tồi.
Andre

84

Tôi khuyên bạn nên sử dụng các hàm dựng sẵn từ jQuery hoặc lodash / Underscore . Chúng đơn giản hơn để sử dụng và dễ đọc hơn.

Cả hai hàm sẽ xử lý trường hợp DRAX được đề cập ... nghĩa là cả hai đều kiểm tra xem (A) biến đó có phải là một chuỗi bằng chữ hay (B) nó là một thể hiện của đối tượng String. Trong cả hai trường hợp, các hàm này xác định chính xác giá trị là một chuỗi.

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

Xem Tài liệu lodash cho _.isString () để biết thêm chi tiết.

Xem Tài liệu jQuery cho $ .type () để biết thêm chi tiết.


97
Đây là điều cốt yếu của những gì sai với cộng đồng JS - kiểm tra đối với kiểu nguyên thủy là một lớp lót và chỉ liên quan đến việc xây dựng ngôn ngữ (một trong những điều cơ bản), nhưng bạn khuyên bạn nên sử dụng thư viện bên ngoài. Nếu ai đó đã sử dụng một trong những thư viện này thì đó có thể là một ý tưởng tốt, nhưng tải xuống chúng chỉ vì điều đó thay vì chỉ kiểm tra loại đó là quá mức cần thiết.
Rafał Wrzeszcz

5
Tôi sẽ đồng ý với Rafal. Tôi thấy mọi nơi đều cải thiện "khả năng đọc" để sử dụng một trong những thư viện bên ngoài này. Nếu bạn biết JavaScript, thì nó dễ đọc hơn một số thư viện bên ngoài mà bạn chưa sử dụng. _.every()là một chút bối rối để sử dụng lúc đầu, và một cái gì đó đơn giản như _.isBoolean()đã làm các nhà phát triển bối rối tại công ty của tôi. Một nhà phát triển nhầm tưởng rằng nó sẽ sai nếu giá trị là boolean và sai. Tiếng Anh dễ đọc hơn tiếng Đức đối với tôi, vì tôi không biết tiếng Đức. Tìm hiểu JavaScript và tất cả sẽ có ý nghĩa.
John Harding

20
@ RafałWrzeszcz Các thư viện này được sử dụng khá rộng rãi và cung cấp nhiều chức năng hữu ích (và đã được thử nghiệm). Đặc biệt là lodash. Tôi sẽ không đề nghị ai đó tải xuống thư viện chỉ để sử dụng cho một giải pháp này .... nhưng tôi sẽ khuyên mọi nhà phát triển javascript tải xuống thư viện này và xem họ đang bỏ lỡ điều gì. ;)
ClearCloud8

13
Tất cả các bạn đều thiếu điểm của một thư viện như Lodash: không phải tốc độ. Không "dễ phát triển". Lý do sử dụng một thư viện như Lodash cung cấp "khả năng phòng thủ" chống lại các vấn đề sẽ làm nổ tung ứng dụng js của bạn. Lỗi nghiêm trọng xảy ra khi bạn cố gắng thực hiện các thao tác chuỗi trên một đối tượng (hoặc ngược lại) và Lodash cung cấp giá trị to lớn xung quanh việc ngăn chặn các lỗi đó.
Random_user_name

1
Hãy nhớ rằng nhiều người sẽ làm điều này trong một môi trường giống như Node hoặc Node và rất ít người sẽ sử dụng jQuery ở đó.
Matt Fletcher

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

Tôi thấy điều đó ở đây:

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


4
Tôi nghĩ rằng giải pháp này là mạnh mẽ nhất vì nó xử lý các tình huống tham chiếu khung chéo / cửa sổ chéo như được đề cập trong URL được cung cấp trong câu trả lời.
EWH

1
Câu trả lời tuyệt vời, có vẻ như Underscore.js cũng sử dụng phương pháp này!
Daan

1
@ling Chỉ tò mò thôi, tại sao bạn lại đặt dấu ngoặc đơn Object.prototype.toString.call(obj) === '[object String]'?
StubbornShowaGuy

@Earlee Ý bạn là (x === y)có khả năng đọc tốt hơn x === y?
StubbornShowaGuy

@StubbornShowaGuy Theo tôi, có. Đó cũng là về sự nhất quán. Cá nhân tôi luôn sử dụng dấu ngoặc đơn khi trả về một giá trị.
Aquarelle

28

Cách tốt nhất:

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');

Mỗi trong số này đã được xây dựng bởi hàm lớp thích hợp của nó, như "Object mới ()", v.v.

Ngoài ra, Duck-Typing: "Nếu nó trông giống như một con vịt, đi giống như một con vịt và có mùi giống như một con vịt - đó phải là một mảng" Ý nghĩa, hãy kiểm tra các thuộc tính của nó.

Hi vọng điêu nay co ich.

Biên tập; 12/05/2016

Hãy nhớ rằng, bạn luôn có thể sử dụng kết hợp các phương pháp tiếp cận quá. Đây là một ví dụ về việc sử dụng bản đồ hành động nội tuyến với typeof :

var type = { 'number': Math.sqrt.bind(Math), ... }[ typeof datum ];

Đây là một ví dụ 'thế giới thực' hơn về việc sử dụng bản đồ nội tuyến:

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

Hàm này sẽ sử dụng [tùy chỉnh] "kiểu đúc" - thay vào đó là "kiểu - / - ánh xạ giá trị" - để tìm hiểu xem một biến có thực sự "tồn tại" hay không. Bây giờ bạn có thể chia mái tóc khó chịu đó giữa null& 0!

Nhiều khi bạn thậm chí không quan tâm đến loại của nó . Một cách khác để tránh gõ là kết hợp các bộ 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) ...;
}

Cả hai Number.prototype String.prototype có một .toString() method. Bạn chỉ cần đảm bảo rằng chuỗi tương đương của số là giống nhau, và sau đó bạn chắc chắn rằng bạn đã chuyển nó vàohttp hàm dưới dạng a Number. Nói cách khác, chúng tôi thậm chí không quan tâm loại của nó là gì.

Hy vọng rằng cung cấp cho bạn nhiều hơn để làm việc với :)


Bạn sẽ cần một số kiểm tra khác cho các số cũ đơn giản, vì cố gắng lấy thuộc tính hàm tạo của chúng sẽ không thành công:

@torazaburo Làm việc tốt với tôi ngay bây giờ trong bảng điều khiển Chrome. Điều gì khiến bạn nghĩ rằng nó sẽ không hoạt động?
Đánh dấu Amery

2
@torazaburo Bạn có thể muốn chơi với các xác nhận ( (o.constructor === Number || s.constructor === Boolean)). Giai thoại, parseIntNaNlà những công cụ mỏng manh nhưng mạnh mẽ. Chỉ cần nhớ, Not-a-Number là KHÔNG-a-Number, và không xác định có thể được xác định.
Cody

1
a.constructor === Mảng bị sai và đôi khi có thể thất bại, hãy sử dụng Array.isArray xem web.mit.edu/jwalden/www/isArray.html
axkibe

1
Đồng ý, điều này không an toàn. Cách tốt hơn là sử dụng kiểm tra tài sản - Đó là cách duy nhất thực sự không an toàn tại thời điểm này. Ví dụ: if(thing.call) { 'its a function'; }hoặc if(thing.defineProperties) { 'its an object'; }. Cảm ơn cho đầu vào, axkibe!
Cody

17

Tôi không thể thành thật nhìn thấy lý do tại sao một người sẽ không đơn giản sử dụng typeoftrong trường hợp này:

if (typeof str === 'string') {
  return 42;
}

Có, nó sẽ thất bại trước các chuỗi được bọc đối tượng (ví dụ new String('foo')) nhưng chúng được coi là một thực tiễn xấu và hầu hết các công cụ phát triển hiện đại có khả năng không khuyến khích sử dụng chúng. (Nếu bạn thấy một cái, chỉ cần sửa nó!)

Thủ Object.prototype.toStringthuật này là thứ mà tất cả các nhà phát triển front-end đã bị kết tội là làm một ngày trong sự nghiệp của họ nhưng đừng để nó đánh lừa bạn bởi sự thông minh của nó: nó sẽ phá vỡ ngay khi một thứ gì đó khắc phục nguyên mẫu Object:

const isString = thing => Object.prototype.toString.call(thing) === '[object String]';

console.log(isString('foo'));

Object.prototype.toString = () => 42;

console.log(isString('foo'));


15

Tôi thích sử dụng giải pháp đơn giản này:

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

3
Làm thế nào khác với câu trả lời của Cody, 4 năm sau?
Jonathan H

3
Câu trả lời của @Sheljohn Cody là tuyệt vời. Câu trả lời của tôi (văn bản hoàn chỉnh) ngắn hơn và đi thẳng vào vấn đề. Bạn đã hỏi ... :)
ScottyG

Là một hàm, điều này sẽ cần một cách xử lý undefinednull, và vẫn nhận được câu trả lời đúng cho các chuỗi rỗng (cả ''new String('')).
MikeBeaton

@MikeBeaton Không có vấn đề gì : (mystring || false) && mystring.constructor === String. Tôi đã sử dụng false trong trường hợp nó được sử dụng trong một hàm phải trả về boolean.
alans

13

Đây là một ví dụ tuyệt vời về lý do tại sao hiệu suất quan trọng:

Làm một cái gì đó đơn giản như một bài kiểm tra cho một chuỗi có thể tốn kém nếu không được thực hiện đúng.

Ví dụ, nếu tôi muốn viết một hàm để kiểm tra xem có thứ gì đó là một chuỗi không, tôi có thể thực hiện nó theo một trong hai cách:

1) const isString = str => (Object.prototype.toString.call(str) === '[object String]');

2) const isString = str => ((typeof str === 'string') || (str instanceof String));

Cả hai đều khá thẳng về phía trước, vậy điều gì có thể ảnh hưởng đến hiệu suất? Nói chung, các cuộc gọi chức năng có thể tốn kém, đặc biệt nếu bạn không biết những gì đang xảy ra bên trong. Trong ví dụ đầu tiên, có một lệnh gọi hàm đến phương thức toString của Object. Trong ví dụ thứ hai, không có lệnh gọi hàm nào, vì typeof và instanceof là toán tử. Các nhà khai thác nhanh hơn đáng kể so với các cuộc gọi chức năng.

Khi hiệu suất được kiểm tra, ví dụ 1 chậm hơn 79% so với ví dụ 2!

Xem các bài kiểm tra: https://jsperf.com/isopestype


Liên kết kiểm tra đã chết, nhưng tôi tin bạn. Loại thông tin này là siêu quan trọng. IMHO điều này nên, nếu không phải là câu trả lời được đánh giá cao nhất, ít nhất là nhận xét được đánh giá cao nhất về câu trả lời hàng đầu hiện tại.
Bộ giải mã

typeof str === 'string' || str instanceof String(có thể bỏ dấu ngoặc đơn mà tôi thích trong if (..)các trường hợp); bất kể, kiểm tra cả loại nguyên thủy và loại đối tượng trong # 2 là rõ ràng và đủ. Những kiểm tra này nên là "hiếm".
dùng2864740

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

Hoạt động cho cả chuỗi ký tự let s = 'blah'và chuỗi đối tượnglet s = new String('blah')


3
Chú ý! Điều này sẽ thất bại trên các chuỗi trống, vì đó là falsey.
Philipp Sumi

8

Lấy từ 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

Nếu ai đó muốn biết nguồn, đó là github.com/lodash/lodash/blob/master/isString.js
Ricardo Canelas

5

Tôi nghĩ rằng giải pháp @customcommander sẽ đủ cho 90% trường hợp của bạn:

typeof str === 'string'

Nên phục vụ bạn ngay (đơn giản vì bình thường không có lý do để có new String('something') mã của bạn).

Nếu bạn quan tâm đến việc xử lý String đối tượng (ví dụ: bạn mong đợi một số var từ bên thứ 3) thì sử dụng lodash như @ ClearCloud8 có vẻ như là một giải pháp rõ ràng, đơn giản và thanh lịch.

Tuy nhiên tôi sẽ đề nghị thận trọng với các thư viện như lodash do kích thước của chúng. Thay vì làm

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

Điều này mang lại toàn bộ đối tượng lodash lớn, tôi muốn đề xuất một cái gì đó như:

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

Và với gói đơn giản, bạn sẽ ổn (tôi tham khảo mã khách hàng ở đây).


tại sao === khi == là đủ
zavr

4

Nếu bạn làm việc trên môi trường node.js, bạn chỉ cần sử dụng hàm tích hợp isString in utils.

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

Chỉnh sửa: như @Jehy đã đề cập, điều này không được chấp nhận kể từ v4.


Có sự thay thế nào không?
Anthony Kong

3
Tài liệu nói "Sử dụng typeof value === 'string'thay thế."
Ông Rogers

x = new String('x'); x.isString(x);trả về sai . Có util.types.isStringObject()nhưng trả về false cho x = 'x'chuỗi kiểu. Hai chức năng tiện ích hoàn toàn không có tiện ích ...
spinkus

4

Phương thức sau đây sẽ kiểm tra xem có bất kỳ biến nào là một chuỗi không ( bao gồm các biến không tồn tại ).

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

Tôi cũng thấy rằng điều này cũng hoạt động tốt, và nó ngắn hơn rất nhiều so với các ví dụ khác.

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

Bằng cách nối vào các trích dẫn trống, nó biến giá trị thành một chuỗi. Nếu myVarđã là một chuỗi thì câu lệnh if thành công.


3
Vấn đề duy nhất là bạn đang ép buộc một biến khi bạn muốn kiểm tra loại của nó. Điều đó có vẻ hơi đắt đối với tôi khi so sánh với typeof.
Olical

1
Vì vậy, bạn đúng. jsperf cho biết nó chậm hơn khoảng 20% typeofnhưng vẫn nhanh hơn một chút toString. Dù bằng cách nào, tôi đoán tôi chỉ thích cú pháp để ép buộc.
Chris Dolphin

4
cái này không hoạt động với kiểu String; var s = new String('abc'); > s === s + '' > false
dùng5672998

1
Không hoạt động với new Stringcus tạo ra một loại object. w3schools.com/js/tryit.asp?filename=tryjs_opes_object2
Chris Dolphin

Suy nghĩ tốt, nhưng bỏ đi các trường hợp cạnh của đối tượng quấn dây.
Anthony Rutledge

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

Tại sao bạn cần kiểm tra null hoặc không xác định nếu x.constructor === Chuỗi cũng sẽ trả về false cho null hoặc không xác định?
Jules Manson

1
@JulesManson: Nó sẽ ném lỗi, không sản xuất false.
Ry-

3

Tôi thấy kỹ thuật đơn giản này hữu ích để kiểm tra kiểu cho 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

Kỹ thuật tương tự cũng hoạt động với 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

Và cho 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

Tương tự cho Object -

Object(x) === x // true, if x is an object
                // false in every other case

NB, regexps, mảng và hàm cũng được coi là đối tượng.

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)    

Nhưng, kiểm tra Array thì hơi khác một chút -

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

Kỹ thuật này không hoạt động cho Hàm tuy nhiên -

Function(x) === x // always false

var x = new String(x); String(x)===xtrả về sai. tuy nhiên ({}).toString.call(x).search(/String/)>0luôn trả về cho những thứ nghiêm ngặt
không đồng bộ

1
function isClass(x,re){return ({}).toString.call(x).search(re)>0;}; isClass("hello",/String/) hoặc isClass(3,/Number/)hoặcisClass(null,/Null/)
không đồng bộ

2

Một giải pháp đơn giản sẽ là:

var x = "hello"

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

1
Điều này không kiểm tra nếu đó là một chuỗi. Nó tạo thành một chuỗi, rất nhiều thứ có toString()chức năng
Muhammad Umer

7
@MuhammadUmer Có, nó chuyển đổi nó thành một chuỗi nhưng sau đó kiểm tra danh tính so với giá trị ban đầu, điều này sẽ chỉ đúng nếu giá trị ban đầu cũng là một chuỗi.
MrWhite

4
Điều này là sai: bạn không thể mù quáng gọi .toStringbất kỳ giá trị nào; hãy thử nếu x được kiểm tra là null hoặc không xác định, ngoại lệ mã của bạn
user5672998

1
Ý tưởng vẫn có thể sử dụng được. x === Chuỗi (x) là an toàn và hoạt động.
Márton Sári

Có thật không? Giải pháp này có vẻ quá kỳ lạ đối với tôi, vì toString()phương pháp có thể bị ghi đè và có thể ném ngoại lệ (do một số triển khai cụ thể) và kiểm tra của bạn sẽ không hoạt động chắc chắn. Ý tưởng chính là bạn không nên gọi các phương thức không liên quan đến những gì bạn muốn nhận. Tôi thậm chí không nói về chi phí không cần thiết liên quan đến toStringphương pháp. Hạ cấp.
Rustem Zinnatullin

2

Một người trợ giúp đánh máy chữ:

function isFromType(variable, type){
  if (typeof type == 'string') res = (typeof variable == type.toLowerCase())
  else res = (variable.constructor == type)
  return res
}

sử dụng:

isFromType('cs', 'string') //true
isFromType('cs', String) //true
isFromType(['cs'], Array) //true
isFromType(['cs'], 'object') //false

Ngoài ra nếu bạn muốn nó được đệ quy (như Array là Object), bạn có thể sử dụng instanceof .

( ['cs'] instanceof Object //true)


2

Tôi sẽ đi một tuyến đường khác với phần còn lại ở đây, cố gắng cho biết một biến là một cụ thể hay một thành viên của một tập hợp cụ thể, các loại.
JS được xây dựng trên vịt; nếu một cái gì đó giống như một chuỗi, chúng ta có thể và nên sử dụng nó như một chuỗi.

7một chuỗi? Vậy thì tại sao lại /\d/.test(7)làm việc?
{toString:()=>('hello there')}một chuỗi? Vậy thì tại sao lại ({toString:()=>('hello there')}) + '\ngeneral kenobi!'làm việc?
Đây không phải là câu hỏi về nên công việc trên, điểm mấu chốt là họ làm.

Vì vậy, tôi đã thực hiện một duckyString()chức năng
Dưới đây tôi kiểm tra nhiều trường hợp không phục vụ cho các câu trả lời khác. Đối với mỗi mã:

  • đặt một biến giống như chuỗi
  • chạy một hoạt động chuỗi giống hệt nhau trên nó và một chuỗi thực để so sánh các đầu ra (chứng minh rằng chúng có thể được coi như các chuỗi)
  • chuyển đổi chuỗi giống như chuỗi thành chuỗi thực để hiển thị cho bạn duckyString()chuẩn hóa đầu vào cho mã mong đợi chuỗi thực
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');

Điều này nằm trong cùng một hướng !!xđối lập x===truevà kiểm tra nếu một cái gì đó giống như mảng thay vì bắt buộc một mảng thực tế.
Các đối tượng jQuery; chúng là mảng? Không. Họ có đủ tốt không? Vâng, bạn có thể chạy chúng thông qua các Array.prototypechức năng tốt.
Chính sự linh hoạt này mang lại cho JS sức mạnh của nó và việc kiểm tra các chuỗi đặc biệt làm cho mã của bạn ít tương tác hơn.

Đầu ra của ở trên là:

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"

Vì vậy, đó là tất cả về lý do tại sao bạn muốn biết nếu một cái gì đó là một chuỗi.
Nếu, giống như tôi, bạn đến đây từ google và muốn xem liệu có thứ gì đó giống chuỗi không , đây là câu trả lời.
Nó thậm chí không đắt tiền trừ khi bạn làm việc với các mảng char thực sự dài hoặc được lồng sâu.
Điều này là bởi vì tất cả là câu lệnh if, không có hàm nào gọi như thế .toString().
Ngoại trừ nếu bạn đang cố gắng xem liệu một mảng char có các đối tượng chỉ có toString()các ký tự nhiều byte hay không, trong trường hợp đó không có cách nào khác để kiểm tra ngoại trừ tạo chuỗi và đếm các ký tự mà byte tạo thành, tương ứng

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('');
    }
}

Bao gồm các tùy chọn để

  • hỏi phương thức nào được coi là chuỗi-y
  • loại trừ các phương pháp phát hiện chuỗi (ví dụ: nếu bạn không thích .toString())

Dưới đây là nhiều bài kiểm tra hơn vì tôi là người hoàn thành:

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});
  • Tất cả các trường hợp tiêu cực dường như được tính đến
  • Điều này sẽ chạy trên trình duyệt> = IE8
  • Các mảng Char có nhiều byte được hỗ trợ trên các trình duyệt có hỗ trợ chuỗi lặp

Đầu ra:

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

Chỉ cần mở rộng câu trả lời của @ DRAX , tôi sẽ làm điều này:

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);
}

Nó cũng sẽ tính đến nulls và undefinedcác loại, và nó sẽ chăm sóc các loại không phải chuỗi, chẳng hạn như 0.


1

Điều này là đủ tốt cho tôi.

CẢNH BÁO: Đây không phải là một giải pháp hoàn hảo. Xem dưới cùng của bài viết của tôi.

Object.prototype.isString = function() { return false; };
String.prototype.isString = function() { return true; };

var isString = function(a) {
  return (a !== null) && (a !== undefined) && a.isString();
};

Và bạn có thể sử dụng như thế này dưới đây.

//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"));

CẢNH BÁO: Điều này hoạt động không chính xác trong trường hợp:

//this is not a string
var obj = {
    //but returns true lol
    isString: function(){ return true; }
}

isString(obj) //should be false, but true

-1

Bạn có thể sử dụng chức năng này để xác định loại của bất cứ điều gì:

var type = function(obj) {
    return Object.prototype.toString.apply(obj).replace(/\[object (.+)\]/i, '$1').toLowerCase();
};

Để kiểm tra xem một biến có phải là một chuỗi không:

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

Tôi không chắc nếu bạn muốn biết đó là loại stringbất kể nội dung của nó hay nội dung của nó là số hay chuỗi, bất kể loại đó là gì.

Vì vậy, để biết loại của nó là một chuỗi, điều đó đã được trả lời.
Nhưng để biết dựa trên nội dung của nó nếu đó là một chuỗi hoặc một số, tôi sẽ sử dụng điều này:

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

Và cho một số ví dụ:

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

Tôi nghĩ ban đầu tôi hỏi cách kiểm tra loại, mặc dù lúc đó tôi không biết cách tạo câu hỏi. (và tôi có lẽ chỉ cần làm điều này /^\d+$/.test('123')để tránh sự phức tạp của các vấn đề phân tích tiềm năng)
Olical
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.