在大多數人的眼裏,js是一門面向對象(Object-Oriented)的語言,可是它與其餘的語言好比c++,java 這些面嚮對象語言 略有不一樣。
!!!艹,說人話
那問幾個問題吧:java
1.你知道js中對象的定義是什麼嗎?c++
答: 不就是一個散列表嘛~ 至關於key/value對.es6
var obj = { name:"jimmy", gender:"male" }
2.那js裏面一切都是對象你能理解嗎?具體一點,你說一下,函數爲何是對象吧。
答:...。 (Ps:md!!! 函數哪裏是對象了。。。)面試
以上對話實際上是一道面試題。 是否是感受本身濛濛噠了~
壯士磨嘰, 其實js裏面一切都是對象是徹底有理有據的。但願可以好好理解,由於這個之後可能會區別你是磚家,仍是專家的一個重要分水嶺.
來咱們先說一說對象.函數
這個問題就涉及了對象的定義。 上面說的沒錯,對象其實就是一個散列表而已。可是更深層次的說,你怎麼得到一個對象。
show me u code:指針
var obj = new Object();
上面一個例子很好的體現出,對象如何定義。
對象實際上是由 new + 構造函數 建立的。 關於這點就會涉及到模式的概念,你們有興趣能夠參考我前面一篇文章——"模式之辯". 並且還有一個限制, 你所建立的類型必須是引用類型。
聽不懂了吧~
總結下上面的,其實
對象 = new + 構造函數 || 字面量的引用類型
來上個栗子.code
var obj = new Function(); //對象 var obj = new Object(); //對象 var obj = {}; //對象 var str = "not a Object"; //不是對象
因爲string不是引用類型,因此它建立的實例不是對象~ 並且其餘的都是引用類型,因此結果都是對象.
可是對象還有幾個features, which are unique with other types.對象
1.對象的可增添性ip
什麼意思嘞?內存
var obj = {}; obj.name = "jimmy"; console.log(obj.name); //jimmy var str = "a"; str.name = "jimmy"; console.log(str.name); //undefined
這個能夠充分的說明,對象類型和值類型的區別的。
2.等價判斷
怎麼判斷兩個對象是一個東西嘞?
用"==="唄。 來試一試.
var obj1 = new Object(); var obj2 = new Object(); console.log(obj1===obj2); //false
艹,怎麼會這樣,兩個不都是對象嗎?並且我又沒動它。應該同樣啊~~~
騷年,不要把你判斷值類型的方法套在咱們偉大的對象上。
說明一下。若是判斷對象類型和值類型。
對象類型的判斷:
對象的等價是創建在大家的源是否相同(官方的說法叫地址).
var obj1= new Object(); var obj2 = new Object();
須要搞清楚,使用 new + 構造器 你是在新建實例,即你建立的是不一樣源的對象。
那如何同源嘞?
var obj1 = new Object({ name:"jimmy" }); var obj2 = obj1; //同源 var obj3 = new Object(); obj2.name = "sam"; console.log(obj1.name); //sam console.log(obj1===obj2); //true console.log(obj2===obj3); //false
其實到這裏,咱們須要將咱們之前的所說的對象再抽象一層。 你說使用的var obj1 裏面的obj1 並非對象,而只是一個指針, 指向着這個對象。 那這個對象在哪裏嘞? 在你的內存當中。 艹~~~ 好難理解。
爲了你們更好的理解一切都是對象,我這裏會以大衆的視角來說解的。(固然若是你已經理解了,能夠忽略下面非正式的說法~)
回退~
咱們仍是將obj1和obj2說成是對象。 上面能夠看出,只有是同源的對象纔會相等。
值類型的判斷:
這個就很好說了, 你知道1===1嗎? 恩,知道~~~
恭喜你,你已經知道值類型的判斷了。
var num1 = 2; var num2 = 2; console.log(num1===num2); //true
說了這麼多,那值類型和引用類型到底有哪些呢?
值類型: string,number,Boolean,null,undefined,Symbol(es6纔出的)
引用類型: Object,Array,RegExp,Function,Date
恩,大體就這麼多。
~腳嘚瑪嘚(Ps:日語)
大哥,不對呀~ 爲何有時候我使用string類型的時候又能夠在後面使用方法嘞?您看:
var s = "jimmy"; console.log(s.length); //5
不是說值類型不是對象嗎? 那它怎麼會有對象的feature呢?
對,這個問題問的好~
來,再給你們科普一個類型,基本包裝類型。
我相信寫過2k+代碼的童鞋應該會遇到這樣的狀況。好比我要知道這個字符串是否是空,可使用這樣的判斷:
var s = "jimmy"; if(s.length===0){ console.log("這是一個空的string"); }
咦~ 爲何值類型的又可使用屬性嘞?
事實上, ECMAScript 規定的類型詳細的分有2.5種.
除了上面說的兩種還有一種基本包裝類型.
基本包裝類型: String,Number,Boolean.
其實值類型 包括基本包裝類型的。
那他的特性是什麼嘞?
再看一下上面的例子:
var str= "jimmy"; console.log(str.length); //5 str.length = 6; console.log(str.length); //5
咱們用事實說話, 上面的結果很好的證實了,基本包裝類型的特性。 即 若是你想讀取值類型的相關屬性和方法,
js引擎會默認幫你將值類型,臨時變爲一個對象使用。可是這層保存存在的時間,只是你代碼執行的那一瞬間。
再次證實:
var str = "jimmy"; str.male = "male"; //執行成功,但當即被銷燬 console.log(str.male); //undefined
上面例子的執行過程是
1.給str包裝一層對象實例 2.執行對象的一個特性 3.銷燬這層包裝實例
因此就不難理解,爲何上面會是undefined. (由於沒都沒了,你哪來的定義嘞)。
綜上所述,在js中一切都是對象是不無道理的。
還記得上面說的,對象是由 new + 構造器函數 建立的嗎? 因此說 有構造器的類型,都是對象。 事實上除了null,undefined 這兩個 呆毛。 其餘的類型都有構造器,因此再次聲明一切都是對象是頗有道理的。
最後咱們來回答一下開篇的那個題目,爲何函數也是對象?
若是函數也是對象,那他應該具備對象的一切特性,我這裏偷個懶,就舉他的動態特性吧。
function a (){}; a.move = 1; console.log(a.move); //1
額,不信嗎? 我開大了哈~ 用instanceof 檢測一下
console.log(a instanceof Object); // true
完畢~再補充一點,我整篇都是對象對象的。英文不都是Object. 那爲何Function類型也是Object. RegExp類型也是Object. Object 也是Object. 好了 不繞了, 若是你們若是知道原型鏈這個東西的話,應該知道,全部的構造器的原型的金字塔尖 就是Object. (null不算啊~ 這個呆毛不算,由於Object再往上就是null了);下次面試以前理解一下這句話,我相信,你的評級應該會靠SP 更近一點吧。嘿嘿