簡體   English   中英

對象和原始類型相等

[英]Object and primitive type equality

我知道相同的對象不相等,即:

var obj = { name: "Value" };
var obj2 = { name: "Value" };

console.log("obj equals obj2: " + (obj === obj2)); //evaluates to false

然而原始類型是:

var str = "string1";
var str2 = "string1";

console.log("str equals str2: " + (str === str2)); //evaluates to true

我的問題是為什么。 為什么對象和原語被區別對待? 如果一個對象只是一個空容器,只有你指定放入容器的屬性,為什么容器的相同屬性不能評估相同? 我在SO和其他地方四處尋找這個答案,但沒找到答案。

JS對象在DOM中被視為與原始類型不同的東西嗎?

謝謝

這似乎真的是一個關於===的問題所以我們來看看嚴格的等式比較算法 ,其中第7點說

如果x和y引用同一個對象,則返回true 否則,返回false

那么“同一個對象”是什么意思呢? 這意味着它們不僅看起來像彼此,而且在記憶中也處於相同的位置。 這意味着,當一個對象被唯一一次===對某個對象時,他們同樣的事情。

var a = {},
    b = {}, // identical to `a`
    c = a;  // same as `a`
a === b; // false
a === c; // true
b === c; // false

當變量的值是一個對象時,它不是一個對象:它是對象的引用 包含對同一對象的引用的兩個變量確實相等:

var myObj = { hello: "world" };
var a = myObj;
var b = myObj;

if (a == b) alert("YES!!"); // YES!!

==運算符在兩端都有對象引用時,進行的比較是測試對象是否引用同一對象。 當涉及原始值時,語義是不同的:直接比較值。

通常, ===運算符檢查類型,如果它們相同,則檢查值。 對象類型包含引用,因此,它們必須引用相同的對象並且屬於同一類型。 字符串文字值不是引用,它是一個值,因此===將為字符串文字生成true,但不是“abc” === new String(“abc”),因為后者是一個Object。

更多信息可以在這里找到:從這里可以探索很多細節: 在JavaScript比較中應該使用哪個等於運算符(== vs ===)?

首先,JavaScript對象不是DOM的一部分。 DOM(文檔對象模型)是構成頁面的HTML元素。 他們合作,但沒有直接聯系。

基本上,是的,原語是一個特例。 你可以把它想象成一個原語的值是一個常數(在某種意義上)。

例如,以數字5為例。無論我聲明5多少次,5總是等於5.因此,表示{var a保持值5}等於{var並不是一個延伸。 b持有值5}。 這個概念對字符串來說有點模糊,但它仍然存在。 “abc”的字符串始終與包含“abc”字符串的任何其他變量相同。

這也不適用於對象。

如果有兩個變量持有相同的對象,則它們是等價的。

var a = {};
var b = a;
console.log(a == b); // true
console.log(a === b); // true

但是,如果我們創建兩個看起來相似的對象:

var a = {};
var b = {};
console.log(a == b); // false
console.log(a === b); // false

這一開始看起來有點奇怪,但想想正在進行的內部工作。 考慮到當您將對象傳遞給函數時,如果更改該對象,則會在函數外部將其更改為。 它通過引用傳遞。

這意味着您可以想到存儲在變量中的指針(存儲器地址)。 所以,如果你想象它們中有內存地址(比如0x123456和0x654321),那么它會更有意義(0x123456和0x654321是不同的,所以你不會把它們擴展為相等)。 它們是兩個獨立的東西,在記憶中占據了自己的區域。

說得通?

你可以在幾個層面回答這個問題。

字符串

事實上,是的,就嚴格的比較運算符而言,字符串的處理方式與對象不同。

從語義上講,這比使用strcmp或等效機制來比較兩個字符串更方便。

在實現方面,成本是可以忽略的,因此JavaScript可以為您提供方便。

順便說一句,人們告訴嚴格相等運算符檢查兩個變量是否指向相同的內存位置是錯誤的 對於字符串,如果字符串內容相等,則===將成功,無論它們位於內存中的哪個位置。

對象

在語義上,與數字或字符串等原始類型相反,很難為對象提供一致的比較運算符集。
您可以對相等性進行深入比較,但更大/更低的運算符沒有多大意義。

這里Javascript的選擇相當不一致。

  • 等式比較的語義(be ===== )僅限於引用
    (即如果引用相等,則=====將成功)。

在實施方面,深度比較可能非常昂貴。
還有一些subtelties如何解釋未定義的屬性。

無論如何,JavaScript並沒有選擇實施深度比較,所以如果你想要一個,你必須自己做。
並且已經編寫了數TB的代碼來嘗試並提供理想的深入對象比較功能。

  • 有序的比較處理方式完全不同。

您可以定義一個valueOf方法,該方法將返回您希望用於有序比較的任何原始值,例如

myObject.prototype.valueOf = function(){return this.my_comparison_value; };

如果沒有明確定義, valueOf將默認為"[object Object]"

因此,如果您不提供valueOf方法:

  • <>運算符將始終返回false (哪種有意義)。
  • 無論引用是否相等, >=<=始終返回true
    (這不太有意義)。

現在,如果你痛苦地定義一個valueOf ,那么相等比較仍然不會使用它。
擁有一致行為的唯一方法是組合<=>= ,例如

if (a >= b && a <= b) { // equality using valueOf

對於瀏覽器提供的原始對象(如DOM元素),排序運算符的行為取決於瀏覽器決定返回的默認值。
除非你真的知道你在做什么,否則我不會建議使用它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM