重學JavaScript01:就從面向對象說起吧

{"type":"doc","content":[{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"你真的理解Object嗎?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://www.macmillandictionary.com/dictionary/british/object_1","title":""},"content":[{"type":"text","text":"Macmillan"}]},{"type":"text","text":"的解釋是:"}]},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"a thing that you can see and"},{"type":"text","text":" "},{"type":"link","attrs":{"href":"https://www.macmillandictionary.com/dictionary/british/touch_1","title":null},"content":[{"type":"text","text":"touch"}]},{"type":"text","text":" "},{"type":"text","marks":[{"type":"strong"}],"text":"that is not"},{"type":"text","text":" "},{"type":"link","attrs":{"href":"https://www.macmillandictionary.com/dictionary/british/alive","title":null},"content":[{"type":"text","text":"alive"}]},{"type":"text","text":" "},{"type":"text","marks":[{"type":"strong"}],"text":"and is"},{"type":"text","text":" "},{"type":"link","attrs":{"href":"https://www.macmillandictionary.com/dictionary/british/usually","title":null},"content":[{"type":"text","text":"usually"}]},{"type":"text","text":" "},{"type":"link","attrs":{"href":"https://www.macmillandictionary.com/dictionary/british/solid_1","title":null},"content":[{"type":"text","text":"solid"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"一種你能夠觸摸到的實物,並非活物。"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"新華字典中,對象的基本含義是:"}]},{"type":"blockquote","content":[{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"行動或思考時作爲目標的人或事物"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"特指戀愛的對方"}]}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"“你是我的研究對象,你是我的學習對象,這是今天的討論對象”但如果單獨用,就成了戀愛對方。“這是我對象”"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因此對象在中文世界中並非像英文所指的那麼普世,於是對象成了計算機領域中的專有名詞,代表一切事物的總稱。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"而從英文解釋中,可以體會到,object是人類認知世界,而產生的一種思維抽象。什麼意思呢?也就是人類成長過程中,對眼前事物的感知。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我是兩個孩子的爸爸,我認真觀察過他們,他倆小時候都是先用眼睛看,進入口欲期後用嘴巴感知,這個東西是紅色,那個東西冰冰涼,再然後大人們教他們數數,OK,這是兩個蘋果。於是對象有了屬性和值。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"《面向對象分析與設計中》,Grady Booch 說,從人類認知角度來說,對象是:"}]},{"type":"blockquote","content":[{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"一個可以觸摸或者可以看見的東西;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"人的智力可以理解的東西;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可以指導思考或行動(進行想象或施加動作)的東西。"}]}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對象的特徵是:"}]},{"type":"blockquote","content":[{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對象具有唯一標識性:即使完全相同的兩個對象,也並非同一個對象。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對象有狀態:對象具有狀態,同一對象可能處於不同狀態之下。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對象具有行爲:即對象的狀態,可能因爲它的行爲產生變遷。"}]}]}]}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"計算機中的Object"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在計算機語言的設計中,不同的設計者利用着他們對object理解,來對object進行了描述,也就是我們今天耳熟能詳的,比如Java、C++ 中基於“類”的面相對象編程的概念。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"但Javascript有點特立獨行,使用了“原型("},{"type":"link","attrs":{"href":"https://www.macmillandictionary.com/dictionary/british/prototype","title":""},"content":[{"type":"text","text":"Prototype"}]},{"type":"text","text":")”。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"the first form of something new, made before it is produced in large quantities"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這裏先不展開。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"JavaScript 的Object 之路"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由於產生之時的政治原因,JS受管理層要求模仿Java,於是你看到了創始人 Brendan Eich 在“原型運行時”的基礎上引入了 new、this 等語言特性,使之“看起來更像 Java”。ES6規範之前,甚至有大量的框架將JS改造成基於類來編程,而這樣做的弊端明顯要大於收益。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"JavaScript 的對象特徵"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"幸運的是,任何語言的運行時,類的概念都會被弱化。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對照上面說的,面向對象的三個特徵:唯一、狀態、行爲"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"唯一標識性"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"一般,對所有的語言來說,對象的唯一標識性都是通過"},{"type":"text","marks":[{"type":"strong"}],"text":"內存地址"},{"type":"text","text":"來實現的,對象具有唯一標識的內存地址,也就具有唯一標識了。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"也就是爲什麼,下面的返回爲false:"}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"var o1 = { a: 1 };\nvar o2 = { a: 1 };\nconsole.log(o1 === o2);"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"狀態與行爲"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對不同的語言來說,狀態和行爲會使用不同的描述:"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"C++ 中的“成員變量”和“成員函數”"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Java中的“屬性”和“方法”"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"而在JS中,狀態和行爲統一抽象成了"},{"type":"text","marks":[{"type":"strong"}],"text":"屬性"},{"type":"text","text":"(函數也是一種特殊的對象)。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如下例中,對對象o來說,d 和 f 就是兩個普通的屬性"}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"var o = {\nd: 1,\nf() {\nconsole.log(this.d);\n}\n};"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"也就是說,JS能很好地體現對象的基本特徵。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"JS對象的獨有特色"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"但爲什麼很多人說“JS不是面向對象”的呢?因爲JS的對象設計有其獨有的特點,那就是:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對象具有高度的動態性,因爲JS能在運行時被修改狀態和行爲。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你試過Java在運行時添加向對象添加屬性嗎?JS 能做到!"}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"var o = { a: 1 };\no.b = 2;\nconsole.log(o.a, o.b); //1 2"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"JS的屬性"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"JS爲了提高抽象能力,將屬性設計成了(比別的語言)更加複雜的形勢,提供了"},{"type":"text","marks":[{"type":"strong"}],"text":"數據屬性"},{"type":"text","text":"和*"},{"type":"text","marks":[{"type":"italic"}],"text":"訪問器屬性"},{"type":"text","text":"*兩類。也就是說,JS的屬性並非簡單的名稱(鍵)和值,而是用了一組attribute(特徵)來描述property(屬性)。"}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"數據屬性"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"數據屬性類似其他語言的“屬性”,具有四個特徵。"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"屬性的值:value"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"能否賦值:writable"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"能否被(如for in)枚舉:enumerable"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"能否被更新(改變或刪除):configurable"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"雖然,我們通常只關係值。"}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"訪問器屬性"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"也就是getter/setter屬性,它也有四個特徵。"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"取值時調用:getter"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"設置時調用:setter"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"能否被(如for in)枚舉:enumerable"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"能否被更新(改變或刪除):configurable"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"也就是說,讀和寫的時候,訪問器屬性可以執行代碼,讓讀和寫得到完全不同的值,可以看作一種函數的語法糖。"}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"實踐一下"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這位客官問了,我怎麼沒設置過什麼writable、enumerable、configurable啊?因爲通常我們定義屬性時,其默認值都是true,那我們怎麼看到呢?getOwnPropertyDescripter"}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"var o = { a: 1 };\no.b = 2;\n//a和b皆爲數據屬性\nObject.getOwnPropertyDescriptor(o,\"a\") // {value: 1, writable: true, enumerable: true, configurable: true}\nObject.getOwnPropertyDescriptor(o,\"b\") // {value: 2, writable: true, enumerable: true, configurable: true}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"那如何改變呢?defineProperty"}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"var o = { a: 1 };\nObject.defineProperty(o, \"b\", {value: 2, writable: false, enumerable: false, configurable: true});\n//a和b都是數據屬性,但特徵值變化了\nObject.getOwnPropertyDescriptor(o,\"a\"); // {value: 1, writable: true, enumerable: true, configurable: true}\nObject.getOwnPropertyDescriptor(o,\"b\"); // {value: 2, writable: false, enumerable: false, configurable: true}\no.b = 3;\nconsole.log(o.b); // 2"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"那訪問器屬性呢?"}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"var o = { get a() { return 1 } };\no.a = 2\nconsole.log(o.a); // 1"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"每次訪問屬性都會實行getter 或者setter 函數,因此o.a 每次都得到1。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"總結一下, JS中的對象,實際上是一個“屬性的集合”:"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"屬性的key 爲字符串或Symbol,"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"屬性的value 爲數據屬性特徵值或者訪問器屬性特徵值"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上面例子中的的a就是key,而它的value,是{writable:true,value:1,configurable:true,enumerable:true}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因此,JS的對象與其他語言相比,有些另類。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"特殊卻普通"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"正如我們前面說到的:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"任何語言的運行時,類的概念都會被弱化。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因此JS可以模仿多數面向對象編程範式,比如基於原型,甚至基於類。也正因此,JS是正如其語言標準所說的:JS是一門面向對象的語言。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"既然這樣,我們就不要機械地用JS來模仿其他語言,充分利用它的"},{"type":"text","marks":[{"type":"strong"}],"text":"高度動態性的屬性集合"},{"type":"text","text":"這一對象系統,挖掘它的能力吧。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章