Sự khác biệt giữa typeof và instanceof và khi nào nên sử dụng so với cái khác?


394

Trong trường hợp cụ thể của tôi:

callback instanceof Function

hoặc là

typeof callback == "function"

nó có quan trọng không, sự khác biệt là gì?

Tài nguyên bổ sung:

JavaScript-Garden typeof vs instanceof


2
Tôi tìm thấy câu trả lời của mình ở đây như một giải pháp dễ sử dụng
CrandellWS

1
Có một cách khác để kiểm tra loại bằng cách sử dụng Object.prototype.toString ecma
rab

1
chỉ sử dụng .constructortài sản thay thế.
Muhammad Umer

Nếu bạn tự hỏi về hiệu suất , xem câu trả lời của tôi dưới đây . typeof nhanh hơn trong đó cả hai đều có thể áp dụng (cụ thể là các đối tượng).
Martin Peter

Câu trả lời:


540

Sử dụng instanceofcho các loại tùy chỉnh:

var ClassFirst = function () {};
var ClassSecond = function () {};
var instance = new ClassFirst();
typeof instance; // object
typeof instance == 'ClassFirst'; // false
instance instanceof Object; // true
instance instanceof ClassFirst; // true
instance instanceof ClassSecond; // false 

Sử dụng typeofcho các loại được xây dựng đơn giản:

'example string' instanceof String; // false
typeof 'example string' == 'string'; // true

'example string' instanceof Object; // false
typeof 'example string' == 'object'; // false

true instanceof Boolean; // false
typeof true == 'boolean'; // true

99.99 instanceof Number; // false
typeof 99.99 == 'number'; // true

function() {} instanceof Function; // true
typeof function() {} == 'function'; // true

Sử dụng instanceofcho các loại được xây dựng phức tạp:

/regularexpression/ instanceof RegExp; // true
typeof /regularexpression/; // object

[] instanceof Array; // true
typeof []; //object

{} instanceof Object; // true
typeof {}; // object

Và điều cuối cùng là một chút khó khăn:

typeof null; // object

11
Câu trả lời này cho thấy rõ lý do tại sao instaceof không nên được sử dụng cho các loại nguyên thủy. Rõ ràng là bạn không có tùy chọn khi nói đến các loại tùy chỉnh, cũng như lợi ích cho các loại 'đối tượng'. Nhưng điều gì làm cho các chức năng gộp lại với "các loại tích hợp đơn giản"? Tôi thấy thật kỳ lạ khi một chức năng hoạt động như một đối tượng, nhưng loại của nó là 'chức năng' làm cho việc sử dụng 'typeof' trở nên khả thi. Tại sao bạn lại không khuyến khích thể hiện của nó?
Đồng hóa

4
@Assimilater bạn cũng có thể sử dụng instanceof với các hàm, tuy nhiên tôi coi 3 quy tắc này rất đơn giản để nhớ và vâng, các hàm là một ngoại lệ :)
Szymon Wygnański

2
một phần khó khăn khác -> chuỗi ví dụ 'Stringof; // sai nhưng Chuỗi mới ('chuỗi ví dụ') thể hiện Chuỗi; // đúng
Luke

2
@Luke nói chung là một ý tưởng tồi để sử dụng "Chuỗi mới" như thế này. mà tạo ra một "đối tượng chuỗi" chứ không phải là một chuỗi nguyên thủy. xem phần tại đây developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/
mẹo

4
Use instanceof for complex built in types- điều này vẫn dễ bị lỗi. Tốt hơn để sử dụng ES5 Array.isArray()et al. hoặc các miếng chêm được đề nghị.
OrangeDog

122

Cả hai đều giống nhau về chức năng bởi vì cả hai đều trả về thông tin loại, tuy nhiên cá nhân tôi thích instanceofvì nó so sánh các loại thực tế hơn là các chuỗi. So sánh kiểu ít bị lỗi của con người và về mặt kỹ thuật sẽ nhanh hơn vì nó so sánh các con trỏ trong bộ nhớ thay vì so sánh toàn bộ chuỗi.


8
có một số tình huống trong đó instanceof sẽ không hoạt động như mong đợi và typeof hoạt động tốt ... developer.mozilla.org/En/Core_JavaScript_1.5_Reference/
Lỗi

55
instanceof hoạt động với các đối tượng trong cùng một cửa sổ. Nếu bạn sử dụng iframe / frame hoặc popup-windows thì mỗi (i) frame / window có đối tượng "function" của riêng chúng và instanceof sẽ thất bại nếu bạn cố so sánh một đối tượng từ một khung / i (i) khác. typeof sẽ hoạt động trong mọi trường hợp vì nó trả về chuỗi "hàm".
một số

14
jsperf.com/typeof-feft-vs-instanceof/3 Tôi đã thử trên Chrome và FF3.X, cách tiếp cận "typeof" nhanh hơn.
Morgan Cheng

10
Đây chỉ là sai. Chúng không giống nhau. Cả hai đều không hoạt động trong tất cả các tình huống giống nhau, đặc biệt là trên các trình duyệt và máy ảo JavaScript khác nhau.
Justin Force

8
Câu trả lời của bạn cho biết "cả hai về cơ bản là giống nhau về chức năng." Trân trọng, đây là giả dối. Như đã nêu và giải thích trong câu trả lời của tôi, không có tùy chọn nào hoạt động trong mọi tình huống, đặc biệt là trên các trình duyệt. Cách tiếp cận tốt hơn là sử dụng cả hai với một | | nhà điều hành.
Justin Force

103

Một lý do tốt để sử dụng typeof là nếu biến có thể không được xác định.

alert(typeof undefinedVariable); // alerts the string "undefined"
alert(undefinedVariable instanceof Object); // throws an exception

Một lý do tốt để sử dụng instanceof là nếu biến có thể là null.

var myNullVar = null;
alert(typeof myNullVar ); // alerts the string "object"
alert(myNullVar  instanceof Object); // alerts "false"

Vì vậy, thực sự theo ý kiến ​​của tôi, nó sẽ phụ thuộc vào loại dữ liệu bạn có thể kiểm tra.


11
+1 cũng lưu ý rằng instanceofkhông thể so sánh với các loại nguyên thủy, typeof có thể.
Tino

3
Trong Chrome 29.0.1541.0 dev undefined instanceof Objecttrả về false và không ném ngoại lệ. Tôi không biết sự thay đổi gần đây như thế nào, nhưng nó làm cho nó instanceofhấp dẫn hơn.
Cypress Frankenfeld

7
undefined instanceof Objectkhông ném một ngoại lệ bởi vì, eh, undefinedđược xác định. Hằng số tồn tại trong không gian tên. Khi một biến không tồn tại (ví dụ do lỗi đánh máy), instanceof sẽ đưa ra một ngoại lệ. Mặt khác, sử dụng typeof trên một biến không tồn tại sẽ mang lại "không xác định".
cleong 28/03/2015

31

Để làm cho mọi thứ rõ ràng, bạn cần biết hai sự thật:

  1. Các instanceof kiểm tra hành liệu thuộc tính prototype của một nhà xây dựng xuất hiện bất cứ nơi nào trong nguyên mẫu chuỗi của một đối tượng. Trong hầu hết các trường hợp, điều này có nghĩa là đối tượng được tạo bằng cách sử dụng hàm tạo này hoặc trên hậu duệ của nó. Nhưng nguyên mẫu cũng có thể được đặt rõ ràng theo Object.setPrototypeOf()phương pháp (ECMAScript 2015) hoặc theo thuộc __proto__tính (trình duyệt cũ, không dùng nữa). Thay đổi nguyên mẫu của một đối tượng không được khuyến khích, vì vấn đề hiệu suất.

Do đó, thể hiện chỉ áp dụng cho các đối tượng. Trong hầu hết các trường hợp, bạn không sử dụng hàm tạo để tạo chuỗi hoặc số. Bạn có thể. Nhưng bạn gần như không bao giờ làm.

Ngoài ra, thể hiện không thể kiểm tra, chính xác hàm tạo nào đã được sử dụng để tạo đối tượng, nhưng sẽ trả về true, ngay cả khi đối tượng được dẫn xuất từ ​​lớp được kiểm tra. Trong hầu hết các trường hợp, đây là hành vi mong muốn, nhưng đôi khi không. Vì vậy, bạn cần phải giữ tâm trí đó.

Một vấn đề khác là phạm vi khác nhau có môi trường thực thi khác nhau. Điều này có nghĩa là chúng có các phần dựng khác nhau (đối tượng toàn cầu khác nhau, các hàm tạo khác nhau, v.v.). Điều này có thể dẫn đến kết quả bất ngờ.

Ví dụ, [] instanceof window.frames[0].Arraysẽ trở lại false, bởi vì Array.prototype !== window.frames[0].Arrayvà mảng kế thừa từ trước đây.
Ngoài ra, nó không thể được sử dụng trên giá trị không xác định, vì nó không có nguyên mẫu.

  1. Các typeof kiểm tra điều hành cho dù giá trị thuộc về một trong sáu loại cơ bản : " số ", " chuỗi ", " boolean ", " đối tượng ", " chức năng " hoặc " không xác định ". Trong đó chuỗi "đối tượng" thuộc về tất cả các đối tượng (ngoại trừ các hàm, là các đối tượng, nhưng có giá trị riêng trong toán tử typeof) và cả giá trị và mảng "null" (đối với "null" thì đó là một lỗi, nhưng lỗi này đã quá cũ , vì vậy nó trở thành một tiêu chuẩn). Nó không dựa vào các hàm tạo và có thể được sử dụng ngay cả khi giá trị không được xác định. Nhưng nó không cung cấp bất kỳ chi tiết nào về các đối tượng. Vì vậy, nếu bạn cần nó, đi đến instanceof.

Bây giờ hãy nói về một điều khó khăn. Điều gì nếu bạn sử dụng constructor để tạo ra một kiểu nguyên thủy?

let num = new Number(5);
console.log(num instanceof Number); // print true
console.log(typeof num); // print object
num++; //num is object right now but still can be handled as number
//and after that:
console.log(num instanceof Number); // print false
console.log(typeof num); // print number

Có vẻ như ma thuật. Nhưng nó không phải như vậy. Nó được gọi là quyền anh (gói giá trị nguyên thủy theo đối tượng) và unboxing (trích xuất giá trị nguyên thủy được bọc từ đối tượng). Loại mã như vậy có vẻ là "một chút" mong manh. Tất nhiên bạn chỉ có thể tránh tạo kiểu nguyên thủy với các hàm tạo. Nhưng có một tình huống khác có thể xảy ra, khi quyền anh có thể đánh bạn. Khi bạn sử dụng Function.call () hoặc Function.apply () trên loại nguyên thủy.

function test(){
  console.log(typeof this);
} 
test.apply(5);

Để tránh điều này, bạn có thể sử dụng chế độ nghiêm ngặt:

function test(){
  'use strict';
  console.log(typeof this);
} 
test.apply(5);

cập nhật: Kể từ ECMAScript 2015, có thêm một loại gọi là Biểu tượng, có loại biểu tượng riêng == "biểu tượng" .

console.log(typeof Symbol());
// expected output: "symbol"

Bạn có thể đọc về nó trên MDN: ( Symbol , typeof ).


2
if an object is created by a given constructor Điều này là không chính xác. o instanceof Csẽ trả về true nếu o kế thừa từ C.prototype. Bạn đã đề cập một vài điều về điều này sau trong câu trả lời của bạn nhưng nó không rõ ràng lắm.
oyenamit

1
không chính xác ... từ cuốn sách: " github.com/getify/You-Dont-Know-JS " một ví dụ của Foo; // true Toán tử instanceof lấy một đối tượng đơn giản làm toán hạng bên trái và một hàm làm toán hạng bên phải của nó. Ví dụ câu hỏi trả lời là: trong toàn bộ chuỗi [[Prototype]] của a, đối tượng có được tùy ý trỏ bởi Foo.prototype bao giờ xuất hiện không?
Deen John

1
Tôi đã chỉnh sửa câu trả lời, để chính xác hơn. Cảm ơn ý kiến ​​của bạn.
Vladimir Liubimov

Ngoài ra, giải thích về vấn đề đấm bốc / unboxing đã được thêm vào.
Vladimir Liubimov

15

Tôi đã phát hiện ra một số hành vi thực sự thú vị (đọc là "khủng khiếp") trong Safari 5 và Internet Explorer 9. Tôi đã sử dụng điều này rất thành công trong Chrome và Firefox.

if (typeof this === 'string') {
    doStuffWith(this);
}

Sau đó, tôi kiểm tra IE9 và nó không hoạt động. Bất ngờ lớn. Nhưng trong Safari, nó không liên tục! Vì vậy, tôi bắt đầu gỡ lỗi và tôi thấy rằng Internet Explorer luôn quay trở lại false. Nhưng điều kỳ lạ nhất là Safari có vẻ là làm một số loại tối ưu hóa trong VM JavaScript của nó, nơi nó là truesự đầu tiên thời gian, nhưng false mỗi lần bạn nhấn tải lại!

Não tôi gần như nổ tung.

Vì vậy, bây giờ tôi đã giải quyết về điều này:

if (this instanceof String || typeof this === 'string')
    doStuffWith(this.toString());
}

Và bây giờ mọi thứ hoạt động tuyệt vời. Lưu ý rằng bạn có thể gọi "a string".toString()và nó chỉ trả về một bản sao của chuỗi, tức là

"a string".toString() === new String("a string").toString(); // true

Vì vậy, tôi sẽ sử dụng cả hai từ bây giờ.


8

Khác biệt thực tế quan trọng khác:

// Boolean

var str3 = true ;

alert(str3);

alert(str3 instanceof Boolean);  // false: expect true  

alert(typeof str3 == "boolean" ); // true

// Number

var str4 = 100 ;

alert(str4);

alert(str4 instanceof Number);  // false: expect true   

alert(typeof str4 == "number" ); // true

7

instanceofcũng hoạt động khi callbacklà một kiểu con của Function, tôi nghĩ


4

instanceoftrong Javascript có thể không ổn định - Tôi tin rằng các khung chính cố gắng tránh sử dụng nó. Các cửa sổ khác nhau là một trong những cách mà nó có thể phá vỡ - tôi tin rằng hệ thống phân cấp lớp cũng có thể gây nhầm lẫn.

Có nhiều cách tốt hơn để kiểm tra xem một đối tượng có phải là một loại tích hợp nhất định hay không (thường là những gì bạn muốn). Tạo các chức năng tiện ích và sử dụng chúng:

function isFunction(obj) {
  return typeof(obj) == "function";
}
function isArray(obj) {
  return typeof(obj) == "object" 
      && typeof(obj.length) == "number" 
      && isFunction(obj.push);
}

Và như thế.


2
Trong trường hợp bạn không biết: typeof không cần dấu ngoặc đơn vì đó là từ khóa và không phải là hàm. Và IMHO bạn nên sử dụng === thay vì ==.
một số

5
@some Bạn nói đúng về typeof nhưng trong trường hợp này không cần ===, chỉ cần khi giá trị được so sánh có thể bằng mà không có cùng loại. Ở đây, nó không thể.
Nicole

@some typeof có bao giờ trả lại một cái gì đó ngoài một chuỗi không?
Kenneth J

Vì vậy, isArray sẽ sai đối với một đối tượng ngăn xếp với phương thức đẩy và thuộc tính độ dài số. Trong trường hợp nào (Arrayof Array) sẽ sai?
Chris Noe

@ChrisNoe vấn đề nảy sinh với các đối tượng chia sẻ giữa nhiều khung: groups.google.com/forum/#!msg/comp.lang.javascript/XTWYCOwC96I/...

3

instanceofsẽ không hoạt động cho người nguyên thủy, ví dụ "foo" instanceof Stringsẽ trở lại falsetrong khi typeof "foo" == "string"sẽ trở lại true.

Mặt khác typeofcó thể sẽ không làm những gì bạn muốn khi nói đến các đối tượng tùy chỉnh (hoặc các lớp, bất cứ điều gì bạn muốn gọi chúng). Ví dụ:

function Dog() {}
var obj = new Dog;
typeof obj == 'Dog' // false, typeof obj is actually "object"
obj instanceof Dog  // true, what we want in this case

Thực tế là các hàm là cả hai nguyên hàm 'hàm' và các thể hiện của 'Hàm', có một chút kỳ lạ khi nó không hoạt động như thế đối với các kiểu nguyên thủy khác, vd.

(typeof function(){} == 'function') == (function(){} instanceof Function)

nhưng

(typeof 'foo' == 'string') != ('foo' instanceof String)

3

Tôi khuyên bạn nên sử dụng nguyên mẫu callback.isFunction().

Họ đã tìm ra sự khác biệt và bạn có thể tin tưởng vào lý do của họ.

Tôi đoán các khung công tác JS khác cũng có những thứ như vậy.

instanceOfTôi sẽ không làm việc trên các chức năng được xác định trong các cửa sổ khác, tôi tin. Chức năng của họ khác với bạn window.Function.


3

Khi kiểm tra một chức năng, người ta phải luôn luôn sử dụng typeof .

Đây là sự khác biệt:

var f = Object.create(Function);

console.log(f instanceof Function); //=> true
console.log(typeof f === 'function'); //=> false

f(); // throws TypeError: f is not a function

Đây là lý do tại sao người ta không bao giờ phải sử dụng instanceofđể kiểm tra chức năng.


Tôi có thể lập luận rằng đó là typeofsai - flà tất cả những điều sau đây: một Object(một đối tượng) và một Function(một chức năng). Ngoại trừ tôi, nó có ý nghĩa hơn để sử dụng instanceofvì biết rằng đó là một chức năng tôi biết nó cũng là một đối tượng, vì tất cả các chức năng là các đối tượng trong ECMAScript. Điều ngược lại là không đúng - biết từ typeofđó fthực sự là một điều objecttôi không biết rằng đó cũng là một chức năng.
Amn

@amn Đối với tôi, đó là một phá vỡ thể hiện của chức năng. Nó được các thuộc tính như length, namecalltừ chức năng, nhưng tất cả chúng đều không còn tồn tại. Điều tồi tệ hơn, nó không thể được gọi và TypeErrornói nó : f is not a function.
maaartinus

2

Sự khác biệt thực tế đáng kể:

var str = 'hello word';

str instanceof String   // false

typeof str === 'string' // true

Đừng hỏi tôi tại sao.


11
Bởi vì đây strlà một chuỗi nguyên thủy, không phải là một đối tượng chuỗi. Điều tương tự cũng xảy ra đối với các nguyên thủy số và các nguyên hàm boolean, chúng không phải là các thể hiện của các đối tác "được xây dựng" của chúng, các đối tượng String, Number và Boolean. JavaScript tự động chuyển đổi ba nguyên thủy này thành các đối tượng khi được yêu cầu (chẳng hạn như sử dụng một phương thức trên chuỗi nguyên mẫu của đối tượng). Mặt trái của sự khác biệt thực tế của bạn, instanceof là tốt hơn để kiểm tra các mảng kể từ đó typeof [] == "object" // true.
Andy E

2

Hiệu suất

typeof nhanh hơn instanceof trong trường hợp cả hai được áp dụng.

Tùy thuộc vào động cơ của bạn, sự khác biệt hiệu suất có lợi typeofcó thể là khoảng 20% . (Số dặm của bạn có thể thay đổi )

Đây là một bài kiểm tra điểm chuẩn cho Array:

var subject = new Array();
var iterations = 10000000;

var goBenchmark = function(callback, iterations) {
    var start = Date.now();
    for (i=0; i < iterations; i++) { var foo = callback(); }
    var end = Date.now();
    var seconds = parseFloat((end-start)/1000).toFixed(2);
    console.log(callback.name+" took: "+ seconds +" seconds.");
    return seconds;
}

// Testing instanceof
var iot = goBenchmark(function instanceofTest(){
     (subject instanceof Array);
}, iterations);

// Testing typeof
var tot = goBenchmark(function typeofTest(){
     (typeof subject == "object");
}, iterations);

var r = new Array(iot,tot).sort();
console.log("Performance ratio is: "+ parseFloat(r[1]/r[0]).toFixed(3));

Kết quả

instanceofTest took: 9.98 seconds.
typeofTest took: 8.33 seconds.
Performance ratio is: 1.198

1
typeof Môn == "mảng" sẽ trả về false. chủ đề typeof là "đối tượng".
Shardul

Làm thế nào đến typeof nhanh hơn? Javascript có thực hiện các chuỗi ký tự không?
Gregory Magarshak

Lý do là: instanceof luôn tuân theo chuỗi nguyên mẫu của đối tượng, vì vậy hình phạt hiệu năng sẽ phụ thuộc vào mức độ trong chuỗi nguyên mẫu là bao nhiêu, instanceofđược thử nghiệm chống lại. Vì vậy, đối với chuỗi thừa kế ngắn, hình phạt sẽ thấp hơn (như [] instanceof Array,, {} instanceof Object) và lâu dài - lớn hơn. Vì vậy, nếu cả hai obj instanceof SomeClasstypeof obj !== 'string'có nghĩa giống nhau theo quan điểm của một số mã giả định của bạn (nếu bạn chỉ thực hiện một bài kiểm tra ifvà không switchthông qua nhiều lớp, v.v.), thì tốt hơn bạn nên chọn thứ hai, thông minh về hiệu suất,
ankhzet

2

Đây chỉ là kiến ​​thức bổ sung cho tất cả các giải thích khác ở đây - tôi không gợi ý sử dụng .constructorở mọi nơi.

TL; DR: Trong các tình huống typeofkhông phải là một lựa chọn và khi bạn biết rằng bạn không quan tâm đến chuỗi nguyên mẫu , Object.prototype.constructorcó thể là một lựa chọn khả thi hoặc thậm chí tốt hơn so với instanceof:

x instanceof Y
x.constructor === Y

Nó đã ở trong tiêu chuẩn kể từ 1.1, vì vậy không phải lo lắng về khả năng tương thích ngược.

Muhammad Umer đã đề cập ngắn gọn điều này trong một bình luận ở đây. Nó hoạt động trên mọi thứ với một nguyên mẫu - vì vậy mọi thứ không nullhoặc undefined:

// (null).constructor;      // TypeError: null has no properties
// (undefined).constructor; // TypeError: undefined has no properties

(1).constructor;                 // function Number
''.constructor;                  // function String
([]).constructor;                // function Array
(new Uint8Array(0)).constructor; // function Uint8Array
false.constructor;               // function Boolean()
true.constructor;                // function Boolean()

(Symbol('foo')).constructor;     // function Symbol()
// Symbols work, just remember that this is not an actual constructor:
// new Symbol('foo'); //TypeError: Symbol is not a constructor

Array.prototype === window.frames.Array;               // false
Array.constructor === window.frames.Array.constructor; // true

Hơn nữa, tùy thuộc vào trường hợp sử dụng của bạn, nó có thể nhanh hơn rất nhiềuinstanceof (lý do có thể là nó không phải kiểm tra toàn bộ chuỗi nguyên mẫu). Trong trường hợp của tôi, tôi cần một cách nhanh chóng để kiểm tra xem giá trị có phải là một mảng được gõ không:

function isTypedArrayConstructor(obj) {
  switch (obj && obj.constructor){
    case Uint8Array:
    case Float32Array:
    case Uint16Array:
    case Uint32Array:
    case Int32Array:
    case Float64Array:
    case Int8Array:
    case Uint8ClampedArray:
    case Int16Array:
      return true;
    default:
      return false;
  }
}

function isTypedArrayInstanceOf(obj) {
  return obj instanceof Uint8Array ||
    obj instanceof Float32Array ||
    obj instanceof Uint16Array ||
    obj instanceof Uint32Array ||
    obj instanceof Int32Array ||
    obj instanceof Float64Array ||
    obj instanceof Int8Array ||
    obj instanceof Uint8ClampedArray ||
    obj instanceof Int16Array;
}

https://run.perf.zone/view/isTypedArray-constructor-vs-instanceof-1519140393812

Và kết quả:

Chrome 64.0.3282.167 (64-bit, Windows)

Đã nhập phiên bản Arrayof vs constructor - nhanh hơn 1,5 lần trong Chrome 64.0.3282.167 (64-bit, Windows)

Firefox 59.0b10 (64-bit, Windows)

Nhập phiên bản Arrayof vs constructor - nhanh hơn 30 lần trong Firefox 59.0b10 (64-bit, Windows)

Vì tò mò, tôi đã làm một tiêu chuẩn đồ chơi nhanh chống lại typeof; đáng ngạc nhiên là nó không hoạt động kém hơn nhiều và dường như Chrome còn nhanh hơn một chút:

let s = 0,
    n = 0;

function typeofSwitch(t) {
    switch (typeof t) {
        case "string":
            return ++s;
        case "number":
            return ++n;
        default:
            return 0;
    }
}

// note: no test for null or undefined here
function constructorSwitch(t) {
    switch (t.constructor) {
        case String:
            return ++s;
        case Number:
            return ++n;
        default:
            return 0;
    }
}

let vals = [];
for (let i = 0; i < 1000000; i++) {
    vals.push(Math.random() <= 0.5 ? 0 : 'A');
}

https://run.perf.zone/view/typeof-vs-constructor-opes-or-number-1519142623570

LƯU Ý: Thứ tự các chức năng được liệt kê chuyển đổi giữa các hình ảnh!

Chrome 64.0.3282.167 (64-bit, Windows)

Kiểu chuỗi / Số so với hàm tạo - nhanh hơn 1,26 lần trong Chrome 64.0.3282.167 (64-bit, Windows)

Firefox 59.0b10 (64-bit, Windows)

LƯU Ý: Thứ tự các chức năng được liệt kê chuyển đổi giữa các hình ảnh!

Chuỗi / Số kiểu so với hàm tạo - chậm hơn 0,78x trong Firefox 59.0b10 (64-bit, Windows)


1

Sử dụng instanceof vì nếu bạn thay đổi tên của lớp, bạn sẽ gặp lỗi trình biên dịch.


1

var newObj =  new Object;//instance of Object
var newProp = "I'm xgqfrms!" //define property
var newFunc = function(name){//define function 
	var hello ="hello, "+ name +"!";
	return hello;
}
newObj.info = newProp;// add property
newObj.func = newFunc;// add function

console.log(newObj.info);// call function
// I'm xgqfrms!
console.log(newObj.func("ET"));// call function
// hello, ET!

console.log(newObj instanceof Object);
//true
console.log(typeof(newObj));
//"object"


Tôi nên làm gì, tôi có thể lấy UA (navigator.userAgent) không?
xgqfrms

0

Đến từ sự dạy dỗ OO nghiêm ngặt mà tôi muốn

callback instanceof Function

Các chuỗi có xu hướng chính tả khủng khiếp của tôi hoặc lỗi chính tả khác. Thêm vào đó tôi cảm thấy nó đọc tốt hơn.


0

Mặc dù instanceof có thể là một chút nhanh hơn sau đó typeof , tôi thích thứ hai vì một ma thuật có thể như vậy:

function Class() {};
Class.prototype = Function;

var funcWannaBe = new Class;

console.log(funcWannaBe instanceof Function); //true
console.log(typeof funcWannaBe === "function"); //false
funcWannaBe(); //Uncaught TypeError: funcWannaBe is not a function

0

Một trường hợp nữa là bạn chỉ có thể đối chiếu với instanceof - nó trả về đúng hoặc sai. Với typeofbạn có thể nhận được loại cung cấp một cái gì đó


0

với hiệu suất trong tâm trí, bạn nên sử dụng typeof với phần cứng thông thường, nếu bạn tạo một tập lệnh có vòng lặp 10 triệu lần lặp thì hướng dẫn: typeof str == 'string' sẽ mất 9ms trong khi chuỗi 'chuỗi' của chuỗi sẽ mất 19ms


0

Tất nhiên là có vấn đề ........!

Chúng ta hãy làm điều này với các ví dụ. Trong ví dụ của chúng tôi, chúng tôi sẽ khai báo hàm theo hai cách khác nhau.

Chúng tôi sẽ sử dụng cả hai function declarationHàm xây dựng . Chúng tôi sẽ làm thế nào typeofinstanceofhành xử trong hai kịch bản khác nhau.

Tạo hàm bằng cách khai báo hàm:

function MyFunc(){  }

typeof Myfunc == 'function' // true

MyFunc instanceof Function // false

Có thể giải thích cho kết quả khác nhau như vậy, khi chúng tôi thực hiện khai báo hàm, typeofcó thể hiểu rằng đó là một hàm. typeofBởi vì kiểm tra xem biểu thức của loại nào đang hoạt động hay không , trong trường hợp của chúng tôi có thực hiện Phương thức gọi hay không . Nếu nó thực hiện phương thức thì đó là một hàm. Ngược lại, không. Làm rõ kiểm tra đặc tả ecmascript cho typeof .MyFunc Call

Tạo hàm bằng hàm tạo:

var MyFunc2 = new Function('a','b','return a+b') // A function constructor is used 

typeof MyFunc2 == 'function' // true

MyFunc2 instanceof Function // true

Ở đây typeofkhẳng định đó MyFunc2là một chức năng cũng như instanceoftoán tử. Chúng tôi đã biết typeofkiểm tra xemMyFunc2Call phương thức đã thực hiện hay chưa. Đó MyFunc2là một hàm và nó thực hiện callphương thức, đó là cách typeofbiết đó là một hàm. Mặt khác, chúng ta đã sử dụng function constructorđể tạo ra MyFunc2nó trở thành một ví dụ của Function constructor. Đó là lý do tại sao instanceofcũng giải quyết true.

Những gì an toàn hơn để sử dụng?

Như chúng ta có thể thấy trong cả hai trường hợp, typeoftoán tử có thể khẳng định thành công rằng chúng ta đang xử lý một hàm ở đây, nó an toàn hơn instanceof. instanceofsẽ thất bại trong trường hợp function declarationfunction declarationskhông phải là một ví dụ Function constructor.

Thực hành tốt nhất :

Như Gary Rafferty đã đề xuất, cách tốt nhất nên sử dụng cả typeof và instanceof cùng nhau.

  function isFunction(functionItem) {

        return typeof(functionItem) == 'function' || functionItem instanceof Function;

  }

  isFunction(MyFunc) // invoke it by passing our test function as parameter

bất kỳ lời phê bình mang tính xây dựng nào liên quan đến câu trả lời này sẽ được đánh giá cao.
AL-zami

0

Để được rất chính xác instanceof nên được sử dụng khi giá trị được tạo ra thông qua các nhà xây dựng (thường loại tùy chỉnh) cho ví dụ

var d = new String("abc")

trong khi typeof để kiểm tra các giá trị được tạo chỉ bằng các bài tập cho ví dụ

var d = "abc"

0

không cần phải quá tải với hàng tấn ví dụ trên, chỉ cần ghi nhớ hai quan điểm:

  1. typeof var;là một toán tử đơn nguyên sẽ trả về kiểu gốc hoặc kiểu gốc của var. do đó nó sẽ trở lại loại nguyên thủy ( string, number, bigint, boolean, undefined, và symbol) hoặc objectloại.

  2. trong trường hợp đối tượng cấp cao hơn, như các đối tượng tích hợp (Chuỗi, Số, Boolean, Mảng ..) hoặc các đối tượng phức tạp hoặc tùy chỉnh, tất cả chúng đều là objectloại gốc, nhưng loại đối tượng được xây dựng dựa trên chúng là khác nhau (như lớp OOP Khái niệm thừa kế), ở đây a instanceof A- một toán tử nhị phân - sẽ giúp bạn, nó sẽ đi qua chuỗi nguyên mẫu để kiểm tra xem hàm tạo của toán hạng bên phải (A) có xuất hiện hay không.

vì vậy bất cứ khi nào bạn muốn kiểm tra "kiểu gốc" hoặc làm việc với biến nguyên thủy - sử dụng "typeof", nếu không thì sử dụng "instanceof".

nulllà một trường hợp đặc biệt, có vẻ như nguyên thủy, nhưng thực sự là một trường hợp đặc biệt cho đối tượng. Sử dụng a === nullđể kiểm tra null thay thế.

mặt khác, functioncũng là một trường hợp đặc biệt, là đối tượng tích hợp sẵn nhưng typeoftrả vềfunction

như bạn có thể thấy instanceofphải đi qua chuỗi nguyên mẫu trong khi typeofchỉ cần kiểm tra loại gốc một lần để dễ hiểu tại sao typeofnhanh hơninstanceof


0

Theo tài liệu MDN về typeof , các đối tượng được khởi tạo bằng từ khóa "mới" thuộc loại 'đối tượng':

typeof 'bla' === 'string';

// The following are confusing, dangerous, and wasteful. Avoid them.
typeof new Boolean(true) === 'object'; 
typeof new Number(1) === 'object'; 
typeof new String('abc') === 'object';

Trong khi tài liệu về các điểm thể hiện rằng:

const objectString = new String('String created with constructor');
objectString instanceOf String; // returns true
objectString instanceOf Object; // returns true

Vì vậy, nếu người ta muốn kiểm tra ví dụ rằng một cái gì đó là một chuỗi bất kể nó được tạo ra như thế nào, cách tiếp cận an toàn nhất sẽ được sử dụng instanceof.

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.