javascript用法 JavaScript中的instanceof運算符是什麼?




typescript instanceof (8)

我認為值得注意的是instanceof是在聲明對象時使用“new”關鍵字定義的。 在JonH的例子中;

var color1 = new String("green");
color1 instanceof String; // returns true
var color2 = "coral";
color2 instanceof String; // returns false (color2 is not a String object)

他沒有提到的是這個;

var color1 = String("green");
color1 instanceof String; // returns false

指定“new”實際上將String構造函數的結束狀態復製到color1 var中,而不是僅將其設置為返回值。 我認為這更好地顯示了新關鍵字的作用;

function Test(name){
    this.test = function(){
        return 'This will only work through the "new" keyword.';
    }
    return name;
}

var test = new Test('test');
test.test(); // returns 'This will only work through the "new" keyword.'
test // returns the instance object of the Test() function.

var test = Test('test');
test.test(); // throws TypeError: Object #<Test> has no method 'test'
test // returns 'test'

使用“new”將函數內部的“this”值賦予聲明的var,而不使用它賦值返回值。

JavaScript中的instanceof關鍵字在第一次遇到時可能會相當混亂,因為人們傾向於認為JavaScript不是面向對象的編程語言。

  • 它是什麼?
  • 它解決了什麼問題?
  • 什麼時候適合,什麼時候不適合?

//Vehicle is a function. But by naming conventions
//(first letter is uppercase), it is also an object
//constructor function ("class").
function Vehicle(numWheels) {
    this.numWheels = numWheels;
}

//We can create new instances and check their types.
myRoadster = new Vehicle(4);
alert(myRoadster instanceof Vehicle);

的instanceof

左手側(LHS)操作數是正在測試右手側(RHS)操作數的實際對象,它是一個類的實際構造函數。 基本定義是:

Checks the current object and returns true if the object
is of the specified object type.

這裡有一些很好的例子 ,下面是一個直接來自Mozilla開發者網站的例子:

var color1 = new String("green");
color1 instanceof String; // returns true
var color2 = "coral"; //no type specified
color2 instanceof String; // returns false (color2 is not a String object)

值得一提的是,如果對象繼承自classe的原型,那麼instanceof評估為true:

var p = new Person("Jon");
p instanceof Person

因為pPerson.prototype繼承,所以pp instanceof Person

根據OP的要求

我已經添加了一些示例代碼和解釋。

當你聲明一個變量時,你給它一個特定的類型。

例如:

int i;
float f;
Customer c;

以上顯示了一些變量,即ifc 。 類型是integerfloat和用戶定義的Customer數據類型。 上述類型可以用於任何語言,而不僅僅是JavaScript。 但是,使用JavaScript聲明變量時,您並未明確定義類型,因此var x ,x可以是數字/字符串/用戶定義的數據類型。 那麼,什麼樣的instanceof會檢查對象,看看它是否是上面指定的類型,然後再採用我們可以執行的Customer對象:

var c = new Customer();
c instanceof Customer; //Returns true as c is just a customer
c instanceof String; //Returns false as c is not a string, it's a customer silly!

上面我們已經看到c是用Customer類型聲明的。 我們已經新建了它並檢查它是否屬於Customer類型。 當然是,它回歸真實。 然後仍然使用Customer對象來檢查它是否是String 。 不,絕對不是一個String我們新建了一個Customer對象而不是一個String對象。 在這種情況下,它返回false。

這真的很簡單!


我想,我剛剛找到了一個真實世界的應用程序,現在會更頻繁地使用它。

如果你使用jQuery事件,有時候你想寫一個更通用的函數,也可以直接調用(沒有事件)。 你可以使用instanceof來檢查函數的第一個參數是否是jQuery.Event一個實例,並做出適當的反應。

var myFunction = function (el) {                
    if (el instanceof $.Event) 
        // event specific code
    else
        // generic code
};

$('button').click(recalc);    // Will execute event specific code
recalc('myParameter');  // Will execute generic code

在我的情況下,函數需要為所有人(通過按鈕上的點擊事件)或只有一個特定的元素來計算東西。 我使用的代碼:

var recalc = function (el) { 
    el = (el == undefined || el instanceof $.Event) ? $('span.allItems') : $(el);
    // calculate...
};

到目前為止,任何一個評論都沒有涉及instanceof的一個重要方面:繼承。 由於原型繼承,使用instanceof進行評估的變量可能會為多個“類型”返回true。

例如,讓我們定義一個類型和一個子類型:

function Foo(){ //a Foo constructor
    //assign some props
    return this;
}

function SubFoo(){ //a SubFoo constructor
    Foo.call( this ); //inherit static props
    //assign some new props
    return this;
}

SubFoo.prototype = new Foo(); // Inherit prototype

現在我們有幾個“類”,讓我們創建一些實例,並找出它們的實例:

var 
    foo = new Foo()
,   subfoo = new SubFoo()
;

alert( 
    "Q: Is foo an instance of Foo? "
+   "A: " + ( foo instanceof Foo ) 
); // -> true

alert( 
    "Q: Is foo an instance of SubFoo? " 
+   "A: " + ( foo instanceof SubFoo ) 
); // -> false

alert( 
    "Q: Is subfoo an instance of Foo? "
+   "A: " + ( subfoo instanceof Foo ) 
); // -> true

alert( 
    "Q: Is subfoo an instance of SubFoo? "
+   "A: " + ( subfoo instanceof SubFoo ) 
); // -> true

alert( 
    "Q: Is subfoo an instance of Object? "
+   "A: " + ( subfoo instanceof Object ) 
); // -> true

看到最後一行? 對一個函數的所有“新”調用都會返回一個從Object繼承的對象。 即使在使用對象創建速記時也是如此:

alert( 
    "Q: Is {} an instance of Object? "
+   "A: " + ( {} instanceof Object ) 
); // -> true

那麼,“類”定義本身呢? 他們是什麼樣的?

alert( 
    "Q: Is Foo an instance of Object? "
+   "A:" + ( Foo instanceof Object) 
); // -> true

alert( 
    "Q: Is Foo an instance of Function? "
+   "A:" + ( Foo instanceof Function) 
); // -> true

我覺得理解任何對像都可以是一個MULTIPLE類型的實例是很重要的,因為你我(錯誤地)認為你可以通過使用instanceof來區分,說和對像以及函數。 最後這個例子清楚地表明函數一個對象。

如果您使用任何繼承模式並且想通過鴨式打字以外的方法來確認對象的後代,這也很重要。

希望能夠幫助任何人探索instanceof


關於“什麼時候適合,什麼時候不適合”的問題,我的2分錢:

instanceof在生產代碼中很少用到,但在你想要聲明你的代碼返回/創建正確類型的對象的測試中很有用。 通過明確您的代碼返回/創建的對像類型,您的測試將變得更加強大,作為理解和記錄代碼的工具。


instanceof只是isPrototypeOf語法糖:

function Ctor() {}
var o = new Ctor();

o instanceof Ctor; // true
Ctor.prototype.isPrototypeOf(o); // true

o instanceof Ctor === Ctor.prototype.isPrototypeOf(o); // equivalent

instanceof僅僅依賴於對象構造函數的原型。

構造函數只是一個正常的函數。 嚴格來說,它是一個函數對象,因為所有東西都是Javascript中的一個對象。 而這個函數對像有一個原型,因為每個函數都有一個原型。

原型只是一個普通的對象,它位於另一個對象的原型鏈中。 這意味著在另一個對象的原型鏈中將對像作為原型:

function f() {} //  ordinary function
var o = {}, // ordinary object
 p;

f.prototype = o; // oops, o is a prototype now
p = new f(); // oops, f is a constructor now

o.isPrototypeOf(p); // true
p instanceof f; // true

應該避免使用instanceof操作符,因為它欺騙了JavaScript中不存在的類。 儘管class關鍵字不在ES2015中,因為class再次只是語法糖......但這是另一回事。


這裡的其他答案是正確的,但他們沒有深入了解instanceof實際工作的方式,這可能會對某些語言律師感興趣。

JavaScript中的每個對像都有一個原型,可以通過__proto__屬性訪問。 函數也有一個prototype屬性,它是由它們創建的任何對象的初始__proto__ 。 當一個函數被創建時,它會被賦予一個獨特的prototype對象。 instanceof操作符使用這個唯一性給你一個答案。 如果您將它作為函數編寫,那麼以下是instanceof可能的樣子。

function instance_of(V, F) {
  var O = F.prototype;
  V = V.__proto__;
  while (true) {
    if (V === null)
      return false;
    if (O === V)
      return true;
    V = V.__proto__;
  }
}

這基本上解釋了ECMA-262第5.1版(也稱為ES5),第15.3.5.3節。

請注意,您可以將任何對象重新分配給函數的prototype屬性,並且可以在構造完成後重新分配對象的__proto__屬性。 這會給你一些有趣的結果:

function F() { }
function G() { }
var p = {};
F.prototype = p;
G.prototype = p;
var f = new F();
var g = new G();

f instanceof F;   // returns true
f instanceof G;   // returns true
g instanceof F;   // returns true
g instanceof G;   // returns true

F.prototype = {};
f instanceof F;   // returns false
g.__proto__ = {};
g instanceof G;   // returns false




instanceof