2009-01-23 32 views
55

Chỉ cần tò mò:Tại sao 4 không phải là một ví dụ về Số?

  • 4 instanceof Số => sai
  • Số mới (4) instanceof Số => đúng không?

Tại sao điều này? Cùng với chuỗi:

  • 'some string' instanceof String false trả
  • new String('some string') instanceof String => true
  • String('some string') instanceof String cũng trả về false
  • ('some string').toString instanceof String cũng trả về false

Đối với đối tượng, mảng hoặc chức năng loại các nhà điều hành instanceof hoạt động như mong đợi. Tôi chỉ không biết làm thế nào để hiểu điều này.

[những hiểu biết mới]

Object.prototype.is = function() { 
     var test = arguments.length ? [].slice.call(arguments) : null 
      ,self = this.constructor; 
     return test ? !!(test.filter(function(a){return a === self}).length) 
       : (this.constructor.name || 
        (String(self).match (/^function\s*([^\s(]+)/im) 
        || [0,'ANONYMOUS_CONSTRUCTOR']) [1]); 
} 
// usage 
var Newclass = function(){}; // anonymous Constructor function 
var Some = function Some(){}; // named Constructor function 
(5).is();      //=> Number 
'hello world'.is();   //=> String 
(new Newclass()).is();  //=> ANONYMOUS_CONSTRUCTOR 
(new Some()).is();   //=> Some 
/[a-z]/.is();     //=> RegExp 
'5'.is(Number);    //=> false 
'5'.is(String);    //=> true 
+0

bạn phải sử dụng 'Number.prototype.isPrototypeOf (inp)' - cách của bạn cũng sẽ hoạt động nếu được thực hiện đúng: 'inp.constructor === Number'; nó có thể thất bại, bởi vì 'constructor' chỉ là một thuộc tính của nguyên mẫu và có thể được ghi đè! – Christoph

+0

Tôi không chắc tôi hiểu ý của bạn với 'có thể bị ghi đè'. Nó không có nghĩa là tôi có thể ghi đè lên hàm tạo với một số hàm tạo khác (đã thử nó). Number.prototype.isPrototypeOf (4) trả về false bằng cách này, vì vậy tôi không thể sử dụng nó để kiểm tra kiểu giá trị nguyên thủy, tôi có đúng không? – KooiInc

+0

Đó là toàn bộ điểm (nguyên thủy! == bọc nguyên thủy)! Việc kiểm tra các hàm tạo là nguy hiểm vì 'obj ['constructor'] = ???' works! Tôi muốn đề nghị sử dụng hàm 'typeOf()' của tôi; để xử lý nguyên thủy và bọc các nguyên thủy giống nhau, hãy sử dụng 'if (typeOf (x). toLowerCase() === 'string')' – Christoph

Trả lời

57

value instanceof Constructor cũng giống như Constructor.prototype.isPrototypeOf(value) và cả kiểm tra [[Prototype]] - chuỗi value cho lần xuất hiện của một đối tượng cụ thể.

Chuỗi và số là giá trị nguyên thủy, không phải đối tượng và do đó không có [[Prototype]], vì vậy nó sẽ chỉ hoạt động nếu bạn quấn chúng trong đối tượng thông thường (gọi là 'boxing' trong Java).

Ngoài ra, khi bạn chú ý, String(value)new String(value) thực hiện các việc khác nhau: Nếu bạn gọi hàm dựng của các kiểu dựng sẵn mà không sử dụng toán tử new, họ cố chuyển đổi ('đúc') đối số thành loại cụ thể . Nếu bạn sử dụng toán tử new, họ tạo đối tượng bao bọc.

new String(value) tương đương với Object(String(value)), hoạt động tương tự như new Object(String(value)).


Một số chi tiết trên các loại trong JavaScript: ECMA-262 định nghĩa các kiểu dữ liệu sau: Undefined, Null, Boolean, Số, và Chuỗi. Ngoài ra, có loại Đối tượng cho những thứ có thuộc tính.

Ví dụ, chức năng là loại Object (họ chỉ cần có một tài sản đặc biệt gọi là [[Gọi]]), và null là một giá trị nguyên thủy của loại Null. Điều này có nghĩa là kết quả của toán tử typeof không thực sự trả về loại giá trị ...

Theo truyền thống, các đối tượng JavaScript có một thuộc tính khác được gọi là [[Class]]. Bạn có thể nhận được thông qua Object.prototype.toString.call(value) (điều này sẽ trả lại '[objectClassname]').Mảng và chức năng thuộc loại Đối tượng nhưng các lớp của chúng là MảngChức năng.

Thử nghiệm đối với một lớp của đối tượng được nêu ở trên khi instanceof không thành công (ví dụ: khi đối tượng được chuyển giữa ranh giới cửa sổ/khung và không chia sẻ cùng nguyên mẫu).


Ngoài ra, bạn có thể muốn kiểm tra phiên bản cải tiến này của typeof:

function typeOf(value) { 
    var type = typeof value; 

    switch(type) { 
     case 'object': 
     return value === null ? 'null' : Object.prototype.toString.call(value). 
      match(/^\[object (.*)\]$/)[1] 

     case 'function': 
     return 'Function'; 

     default: 
     return type; 
    } 
} 

Đối với nguyên thủy, nó sẽ trở lại của họ loại trong thấp hơn trường hợp, cho các đối tượng, nó sẽ trở lại của họ lớp trong trường hợp tiêu đề.

Ví dụ:

  • Đối với nguyên thủy của loạiSố (ví dụ 5), nó sẽ trở lại 'number', cho các đối tượng wrapper của lớpSố (ví dụ new Number(5)), nó sẽ trả về 'Number';

  • Đối với các chức năng, nó sẽ trả lại 'Function'.

Nếu bạn không muốn phân biệt giữa giá trị nguyên thủy và đối tượng bao bọc (vì lý do nào đó, có thể là xấu), hãy sử dụng typeOf(...).toLowerCase().

Lỗi đã biết là một số chức năng tích hợp trong IE, được coi là 'Object' và giá trị trả lại là 'unknown' khi được sử dụng với một số đối tượng COM +.

+0

@annakata: kiểm tra ECMA-262. các kiểu được gọi là Undefined, Null, Boolean, Number, String và Object; không có vấn đề gì 'typeof' trả về ... – Christoph

+0

@Christoph - nó rất nhiều vấn đề kể từ khi các đối tượng bao bọc là chữ hoa, và typeofs là chữ thường và không có gì khác có thể truy cập. Do đó, quy ước và thực hành là tham chiếu đến các kiểu dữ liệu trong chữ thường như được làm rõ ở đây: https://developer.mozilla.org/En/JS/Glossary – annakata

+0

@annakata: 'typeof' bị hỏng - giá trị trả về của nó không có gì để làm với các loại thực tế! – Christoph

12

Bạn có thể thử để đánh giá:

>>> typeof("a") 
"string" 
>>> typeof(new String("a")) 
"object" 
>>> typeof(4) 
"number" 
>>> typeof(new Number(4)) 
"object" 
1

Đây là một sắc thái của javascript mà tôi đã tìm thấy một số bắt ra. instanceof của toán tử sẽ luôn dẫn đến sai nếu LHS không phải là loại object.

Lưu ý rằng new String('Hello World') không dẫn đến loại string nhưng là object. Toán tử new luôn dẫn đến một đối tượng. Tôi thấy việc này: -

function fnX(value) 
{ 
    if (typeof value == 'string') 
    { 
      \\Do stuff 
    } 
} 
fnX(new String('Hello World')); 

Hi vọng là "Do Stuff" sẽ xảy ra nhưng nó không vì typeof giá trị là đối tượng.

2

Như đã nêu trong câu trả lời của Christoph, chuỗi ký tự và số không giống như đối tượng Chuỗi và Số.Nếu bạn sử dụng bất kỳ Chuỗi hoặc số phương pháp trên theo nghĩa đen, nói

'a string literal'.length 

hiểu theo nghĩa đen là tạm thời chuyển sang một đối tượng, phương pháp này được gọi và đối tượng được loại bỏ.
Văn học có một số ưu điểm khác biệt so với đối tượng.

//false, two different objects with the same value 
alert(new String('string') == new String('string')); 

//true, identical literals 
alert('string' == 'string'); 

Luôn sử dụng các chữ để tránh hành vi không mong muốn!
Bạn có thể sử dụng số() và String() để định kiểu nếu bạn cần phải:

//true 
alert(Number('5') === 5) 

//false 
alert('5' === 5) 
0

Trong trường hợp số nguyên thủy, các phương pháp isNaN nó cũng có thể giúp bạn.

Các vấn đề liên quan