Everything is object (萬物皆對象)。
對象究竟是什麼,咱們能夠從兩個層次來理解。javascript
對象是單個事物的抽象前端
一本書、一輛汽車、一我的均可以是對象,一個數據庫、一張網頁、一個與遠程服務器的鏈接也能夠是對象。當實物被抽象成對象,實物之間的關係就變成了對象之間的關係,從而就能夠模擬現實狀況,針對對象進行編程。
對象是一個容器,封裝了屬性(property)和方法(method)java
屬性是對象的狀態,方法是對象的行爲(完成某種任務)。好比,咱們能夠把動物抽象爲animal對象,使用「屬性」記錄具體是那一種動物,使用「方法」表示動物的某種行爲(奔跑、捕獵、休息等等) 在實際開發中,對象是一個抽象的概念,能夠將其簡單理解爲 : 數據集或功能集。
面向對象只是過程式代碼的一種高度封裝,目的在於提升代碼的開發效率和可維護性
小編的理解:面向對象就是說,使用對象的時候,你能夠直接使用它所提供的功能而忽略其內部組成狀況。面對對象不必定只有在編程界裏纔有,咱們生活中無處不在;好比說,你家裏的電視機,你使用了遙控,就能操做電視機,可是你實際上不知道這臺電視機裏面是什麼零件組成的,你只要知道,我拿到遙控就能夠操做電視機就行了。這就是一種面向對象的思想。數據庫
面向對象編程 —— Object Oriented Programming,簡稱 OOP ,是一種編程開發思想。
它將真實世界各類複雜的關係,抽象爲一個個對象,而後由對象之間的分工與合做,完成對真實世界的模擬。
在面向對象程序開發思想中,每個對象都是功能中心,具備明確分工,能夠完成接受信息、處理數據、發出信息等任務。
所以,面向對象編程具備靈活、代碼可複用、高度模塊化等特色,容易維護和開發,比起由一系列函數或指令組成的傳統的過程式編程(procedural programming),更適合多人合做的大型軟件項目。編程
var obj = { name: "Tom ", sex: " man", age:19, run:function(){ console.log("一天跑一千米"); } }
var obj = new Object(); obj.name = "Tom "; obj.sex = " man"; obj.age = 19; obj.run = function(){ console.log("一天跑一千米"); }
具備相同特性(數據元素)和行爲(功能)的對象的抽象就是類。所以,對象的抽象是類,類的具體化就是對象,也能夠說類的實例是對象,類實際上就是一種數據類型。類具備屬性,它是對象狀態的抽象,用數據結構來描述類的屬性。類具備操做,它是對象行爲的抽象,用操做名和實現該操做的方法來描述。服務器
做爲初學者,容易混淆類和對象的概念。類(Class)是一個抽象的概念,對象則是類的具體實例。好比:人是一個類,司馬遷,李白,杜甫都是對象;首都是一個類,則北京,倫敦,華盛頓,莫斯科都是對象;動物貓是一個類,則Kitty、Grafield 和 Doraemon 都是對象。
咱們能夠說 Kitty 貓的體重是 1.5kg,而不能說貓類的體重是 1.5kg;能夠說李白是詩人,而不能說人類是詩人。狀態是描述具體對象而非描述類的,行爲是由具體對象發出的而非類發出的。數據結構
類與對象的關係就如模具和鑄件的關係,類實例化的結果就是對象,而對象的抽象就是類,類描述了一組有相同特性(屬性)和相同行爲的對象。模塊化
class person{ }//這個是類 $obj = new person();//類的實例化就是對象
// Class 模板 function Person(name,sex,age){ var obj = {}; obj.name = name; obj.sex = sex; obj.age = age; obj.run = function(){ console.log("天天堅持跑步"); } return obj; } // 實例化 var person1 = Person("Tom","sex",19); //操做 person1.run(); // 輸出結果:天天堅持跑步
優勢:
一、 在工廠模式中,用戶只須要知道所要生產的具體東西,無須關心具體的建立過程,甚至不須要具體產品類的類名。
二、 在系統增長新的產品時,咱們只須要添加一個具體產品類和對應的實現工廠,無需對原工廠進行任何修改,很好地符合了「開閉原則」。
缺點:
一、 每次增長一個產品時,都須要增長一個具體類和對象實現工廠,使得系統中類的個數成倍增長,在必定程度上增長了系統的複雜度,同時也增長了系統具體類的依賴。這並非什麼好事。函數
//構造函數(這裏就建立了一個Class模板) function Person(name,sex,age){ this.name = name; this.sex = sex; this.age = age; this.run = function(){ console.log("天天堅持跑步"); } } // 實例化 ( new Object()) var person1 = new Person("Tom","man",19); //操做 person1.run();// 天天堅持跑步
// 構造全局的對象 var action = { run:function(){ console.log("天天堅持跑步"); } } //構造函數 funcction(name,sex,age){ this.name = name; this.sex = sex; this.age = age; this.run = action.run; } //實例化 var person1 = new Person("Tom","man",19); person1.run();
分析: 爲何要改進構造函數?
咱們都知道當實例化一個對象後,那麼這個對象就擁有了模板的屬性和方法,
當咱們使用方法時首先會在內存中開闢一份空間,而後在執行相應的操做。假設咱們實例化一萬個對象,那麼這一萬個對象在執行方法時都要在內存中開闢空間,這樣只會浪費內存的空間,這時若是能用一個操做代替一萬個操做那樣豈不是美哉,因此小編這裏用了一個全局的對象,即便是一萬個對象使用這個方法只會在內存中開闢一份空間。
可是這也有缺點,咱們都知道全局變量和局部變量,全局變量易形成污染而且聲明週期比較長,那麼全局對象也是同樣的,有沒有一種方式能夠不用所有對象呢?固然有,見下面的第三種建立模式學習
//構造函數 function Person(name,sex,age){ this.name = name; this.sex = sex; this.age = age; } //使用原型對象 Object.prototype Person.prototype.run = function() { console.log("天天堅持跑步"); } //實例化 var person1 = new Person("Tom","man",19); person1.run();// 天天堅持跑步
首先先明白幾個屬性:
__proto__: 對象的原型。全部對象都有(包括函數)
prototype:函數的原型對象。只有函數(準確來講是構造函數)纔有
constructor:對象上的一個屬性,默認指向這個原型的構造函數
首先必需要說的是,this的指向在函數定義的時候是肯定不了的,只有函數執行的時候才能肯定this到底指向誰,實際上this的最終指向的是那個調用它的對象(這句話有些問題,後面會解釋爲何會有問題,雖然網上大部分的文章都是這樣說的,雖然在不少狀況下那樣去理解不會出什麼問題,可是實際上那樣理解是不許確的,因此在你理解this的時候會有種琢磨不透的感受),那麼接下來我會深刻的探討這個問題。
eg1:
function show(){ var user = "Tom"; console.log(this.user);//undefined console.log(this);//window } show();
按照咱們上面說的this最終指向的是調用它的對象,這裏的函數show()實際是被Window對象所調用出來的,下面的代碼就能夠證實。
function show(){ var user = "Tom"; console.log(this.user);//undefined console.log(this);//window } window.show();
和上面代碼結果同樣,因此此時this是window調用出來的
eg2:
var show = { user:"Tom", fn:function(){ console.log(this.user);//Tom } } show.fn();
這裏的this指向的是對象show,由於你調用這個fn是經過show.fn()執行的,那天然指向就是對象show,這裏再次強調一點,this的指向在函數建立的時候是決定不了的,在調用的時候才能決定,誰調用的就指向誰,必定要搞清楚這個。
要想完全搞懂this的指向請看下面的例子
eg3:
var show = { user:"Tom", fn:function(){ console.log(this.user);//Tom } } window.show.fn();
這段代碼和上面的那段代碼幾乎是同樣的,可是這裏的this爲何不是指向window,若是按照上面的理論,最終this指向的是調用它的對象,這裏先說個而外話,window是js中的全局對象,咱們建立的變量其實是給window添加屬性,因此這裏能夠用window點show對象。
這裏先不解釋爲何上面的那段代碼this爲何沒有指向window,咱們再來看一段代碼
var show = { a:20, b:{ a:22, fn:function(){ console.log(this.a);// 22 } } } show.b.fn();
這裏一樣也是對象show點出來的,可是一樣this並無執行它,那你確定會說我一開始說的那些不就都是錯誤的嗎?其實也不是,只是一開始說的不許確,接下來我將補充一句話,我相信你就能夠完全的理解this的指向的問題。
狀況1:若是一個函數中有this,可是它沒有被上一級的對象所調用,那麼this指向的就是window,這裏須要說明的是在js的嚴格版中this指向的不是window,可是咱們這裏不探討嚴格版的問題,你想了解能夠自行上網查找。
狀況2:若是一個函數中有this,這個函數有被上一級的對象所調用,那麼this指向的就是上一級的對象。
狀況3:若是一個函數中有this,這個函數中包含多個對象,儘管這個函數是被最外層的對象所調用,this指向的也只是它上一級的對象,例子3能夠證實,若是不相信,那麼接下來咱們繼續看幾個例子。
var show = { a:20, b:{ fn:function(){ console.log(this.a);// undefined } } } show.b.fn();
儘管對象b中沒有屬性a,這個this指向的也是對象b,由於this只會指向它的上一級對象,無論這個對象中有沒有this要的東西。
還有一種比較特殊的狀況,eg4:
var show = { a:20, b:{ a:22, fn:function(){ console.log(this.a);// undefined console.log(this);//window } } } var d = show.b.fn; d();
這裏this指向的是window,是否是有些蒙了?實際上是由於你沒有理解一句話,這句話一樣相當重要。
this永遠指向的是最後調用它的對象,也就是看它執行的時候是誰調用的,例子4中雖然函數fn是被對象b所引用,可是在將fn賦值給變量d的時候並無執行因此最終指向的是window,這和例子3是不同的,例子3是直接執行了fn。
this講來說去其實就是那麼一回事,只不過在不一樣的狀況下指向的會有些不一樣,上面的總結每一個地方都有些小錯誤,也不能說是錯誤,而是在不一樣環境下狀況就會有不一樣,因此我也沒有辦法一次解釋清楚,只能你慢慢地的去體會。
構造函數版this:
function Fn(){ this.user = "Tom"; } var a = new Fn(); console.log(a.user); //Tom
這裏之因此對象a能夠點出函數Fn裏面的user是由於new關鍵字能夠改變this的指向,將這個this指向對象a,爲何我說a是對象,由於用了new關鍵字就是建立一個對象實例,理解這句話能夠想一想咱們的例子3,咱們這裏用變量a建立了一個Fn的實例(至關於複製了一份Fn到對象a裏面),此時僅僅只是建立,並無執行,而調用這個函數Fn的是對象a,那麼this指向的天然是對象a,那麼爲何對象a中會有user,由於你已經複製了一份Fn函數到對象a中,用了new關鍵字就等同於複製了一份。
當this碰到return:
function Fn(){ this.user = "Tom"; return {}; } var a = new Fn(); console.log(a.user);//undefined
繼續:
function Fn(){ this.user = "Tom"; return funciton(){}; } var a = new Fn(); console.log(a.user);//undefined
goon:
function Fn(){ this.user = "Tom"; return 1; } var a = new Fn(); console.log(a.user);// Tom
再繼續:
function Fn(){ this.user = "Tom"; return undefined; } var a = new Fn(); console.log(a.user);//Tom
若是返回值是一個對象,那麼this指向的就是那個返回的對象,若是返回值不是一個對象那麼this仍是指向函數的實例
function Fn(){ this.user = "Tom"; return null; } var a = new Fn(); console.log(a.user);//Tom
雖然null也是對象,可是在這裏this仍是指向那個函數的實例,由於null比較特殊
這是今天學的看的全部內容,但願對正在學習前端的朋友有所幫助,有什麼問題能夠留言,咱們一塊兒進步!