2011-03-05 140 views
50

我繼承了另一位開發人員寫的一些javascript代碼。他不喜歡我們在整個項目中使用的網格組件,所以他決定寫他自己的。他寫的網格不能排序日期,因爲它只能綁定到字符串/數字。他在使用它們之前將所有日期轉換爲字符串。我查看了他編寫的日期函​​數的字符串格式,並且認爲我只需將一個日期屬性添加到具有原始值的字符串中,然後在排序時查看該字符串是否具有日期屬性並根據該屬性進行排序。但是,似乎你不能在javascript中爲字符串添加屬性。我不知道有一些你不能添加屬性的類型。例如:爲什麼我無法將屬性添加到JavaScript中的字符串對象?

<html> 
<script> 
var test = "test"; 
test.test = "test inner"; 
console.log(test); 
console.log(test.test); 
</script> 

test.test將是未定義的。奇怪的。我的問題是爲什麼這段代碼不起作用?此外,如果您可以考慮在該網格上排序日期的任何解決方法(除了實際綁定到日期對象而不是字符串,這將是一個修復的痛苦),這將是非常有用的。

+0

參見:[?是字符串對象(http://stackoverflow.com/questions/5156196/are-strings-object/) – CMS 2011-03-05 02:16:34

回答

69

有6種語言類型中的JavaScript:

  • 5原始類型:字符串布爾未定義
  • 1非原始型: 對象

原始類型的值稱爲原始值,它們不能具有屬性。
對象的值非原始類型被稱爲對象,它們可以具有屬性。

當您嘗試了一個名爲'bar'屬性分配給一個變量foo,像這樣:

foo.bar = 'abc'; 

那麼結果將取決於foo值的類型:

(一)如果foo的值是的類型未定義無效,則會拋出錯誤,

(b)中如果foo值是類型對象,則命名屬性'bar'將對象foo(如果必要)上定義的,並且它的值將被設置爲'abc'

(c)中如果foo值是類型的字符串布爾,則變量foo將不會以任何方式改變。在這種情況下,上述分配操作將是noop

因此,正如你所看到的,如果這些變量是對象,那麼賦值給變量只有意義。如果情況並非如此,那麼這項任務根本就什麼也不做,甚至會出錯。


在你的情況下,變量test包含String類型的值,所以這個:

test.test = "test inner"; 

做什麼都沒有。


但是,由於ES5引入了訪問器屬性,所以我上面說過了一個例外。訪問器屬性允許我們定義在檢索或設置屬性時調用的函數。

例如:

var str = ''; 
str.prop; 

這裏str是拿着字符串值的變量。因此,訪問該變量的屬性應該是無操作的(str.prop僅返回undefined)。這是有一個例外:如果String.prototype包含訪問器屬性'prop'與一個定義的getter,那麼該getter將被調用。

所以,如果這被定義:

Object.defineProperty(String.prototype, 'prop', { 
    get: function() { 
     // this function is the getter 
    } 
}); 

那麼這

str.prop; 

將調用該getter函數。

現場演示:http://jsfiddle.net/fmNgu/

不過,我不認爲加入存取性能的內置原型將是一個很好的做法。

+9

'你不能給屬性賦值'有點令人誤解:由於自動裝箱(更具體地說,ECMA-262第5版第8.7.2節中描述的算法),將屬性分配給基元是完全有效的;然而,這些屬性將被添加到純粹的臨時包裝對象而不是基元中,因此無法獲取屬性(包裝對象不會替換基元)。因此,將一個屬性賦給一個原語是一個noop,除非賦值有副作用(例如,如果該屬性是通過訪問函數實現的) – Christoph 2011-03-05 13:14:31

+0

@Christoph是的,你說得對。我已經更新了我的答案。你可以請實際檢查一下嗎? – 2011-03-05 18:10:18

+2

@Šime:您的回答準確地描述了ECMAScript3的行爲:根據第11.2.1節,屬性訪問調用'ToObject()',它將拋出未定義和空值,爲值創建包裝對象並返回對象的參數;在ES5中,情況稍微複雜一些,因爲您可以將一個setter函數添加到基元的原型對象,即對基元的設置屬性可能會產生副作用... – Christoph 2011-03-05 21:50:31

25

如果您使用String對象,您可以添加屬性:

var test = new String("test"); 
test.test = "test inner"; 
console.log(test.toString()); // prints out "test" 
console.log(test.test); // prints out "test inner" 
+5

它確實有一個缺點。以下返回false:'test ==='test''。這是[爲什麼它那樣](http://stackoverflow.com/questions/10951906/why-does-foo-new-stringfoo-evaluate-to-false-in-javascript)。 – 2012-09-14 14:56:29

+0

你剛剛做了我的一天。我知道......曾經...... – halfbit 2016-05-29 17:05:43

相關問題