JS面向對象一:MVC的面向對象封裝
面向對象(Object-Oriented)
面向對象裏面向的意思是以...爲主,面向對象編程既以對象爲主的編程.
Namespace 命名空間 允許開發人員在一個獨特, 應用相關的名字的名稱下捆綁所有功能的容器。 Class 類 定義對象的特徵。它是對象的屬性和方法的模板定義. Object 對象 類的一個實例。 Property 屬性 對象的特徵,比如顏色。 Method 方法 對象的能力,比如行走。 Constructor 構造函數 對象初始化的瞬間, 被調用的方法. 通常它的名字與包含它的類一致. 例如Object(),String(),Number() Inheritance 繼承 一個類可以繼承另一個類的特徵。 Encapsulation 封裝 一種把數據和相關的方法綁定在一起使用的方法. Abstraction 抽象 結合複雜的繼承,方法,屬性的對象能夠模擬現實的模型。 Polymorphism 多態 多意爲‘許多’,態意爲‘形態’。不同類可以定義相同的方法或屬性。
命名空間
// 全局命名空間 var MYAPP = MYAPP || {};
javascript命名空間 MYAPP包含了所有的命名,他就像一個房間一樣,裝着所有的屬性,所以就叫命名空間
// 給普通方法和屬性創建一個叫做MYAPP.commonMethod的容器 MYAPP.commonMethod = { regExForName: "", // 定義名字的正則驗證 regExForPhone: "", // 定義電話的正則驗證 validateName: function(name){ // 對名字name做些操作,你可以通過使用“this.regExForname” // 訪問regExForName變量 }, validatePhoneNo: function(phoneNo){ // 對電話號碼做操作 } } // 對象和方法一起申明 MYAPP.event = { addListener: function(el, type, fn) { // 代碼 }, removeListener: function(el, type, fn) { // 代碼 }, getEvent: function(e) { // 代碼 } // 還可以添加其他的屬性和方法 } //使用addListener方法的寫法: MYAPP.event.addListener("yourel", "type", callback);
解釋: 因爲
1||2//返回1,不是true或者false!!!
五個falsy值
0
NaN
null
undefined
''
在javascript中,a||b
c&&d
的返回值只會在abcd
中選一個!
且運算符(&&)往往用於多個表達式的求值。 它的運算規則是:如果第一個運算子的布爾值爲true,則返回第二個運算子的值(注意是值,不是布爾值);如果第一個運算子的布爾值爲false,則直接返回第一個運算子的值,且不再對第二個運算子求值。
如果是一連串的&&,他的返回值就是遇到的第一個falsy值,後面的不看了
1 && 0 && console.log(3)//console.log(3)不會執行,返回0
console.log(3)//返回undefined
而||和&&相反
返回第一個爲真的值.後面的不看 那麼:
var a = b || {}
意思就是如果b是存在的(b的返回值爲true
),那麼a=b
,如果b不存在,那麼a={}
類(從MVC提煉面向對象是什麼)
使用的代碼是 模塊化、MVC裏的V和C、閉包與立即執行函數的使用和MVC中的M(model)、MVC總結
接下來優化老版本的message.js 箭頭函數內外this相通
優化前的結構:
在幾個模塊化文件裏,都有MVC
那麼我們可以吧每個js文件中的MVC寫成一個模板,這個模板就是類 所謂模板,就是寫個函數把他造出來,那麼我們來封裝MVC
封裝 Model View Controller
首先建三個封裝的文件,再引入
View():
Model():
原先的model:
封裝後Model():
並且save()傳入object 然後就可以用封裝後的Model()代碼了,修改message.js代碼爲:
也就是說,封裝後我們的使用方法是:
如果有兩個model,不需要寫重複代碼
Controller():
封裝Controller.js,但是沒有將封裝運用,因爲自己的簡歷項目比較小,代碼結構不復雜,封裝後反而會難理解,知道如何封裝和如何使用的思想就可以
總結
密愛想對象封裝後MVC的使用方法: view:
/* var view = View('.xxx') */
model:
/* var model = Model({ resourceName: '表名' }) */
controller:
/* Controller({ init:(){ this.view this.model this.xxx() this.yyy() }, xxx(){}, yyy(){} }) */
簡單了不少.
總結: 面向對象就是既然這些對象有相同的屬性和相同的行爲,那麼就把相同的地方存到一個地方,當做一個模板.這就叫類 當需要生成對象的時候,new一個對象出來,這個對象就有這個模板上的屬性和行爲.這就叫實例化一個對象. 面向對象的核心就是實例化一個對象
其他:對象的方法
以下引用自MDNjavascript面向對象
如果一個Object的的屬性是函數,那麼這個屬性叫方法
在JavaScript中方法通常是一個綁定到對象中的普通函數, 這意味着方法可以在其所在context之外被調用。 思考下面示例中的代碼:
function Person(firstName) { this.firstName = firstName; } Person.prototype.sayHello = function() { alert("Hello, I'm " + this.firstName); }; var person1 = new Person("Alice"); var person2 = new Person("Bob"); var helloFunction = person1.sayHello; person1.sayHello(); // alerts "Hello, I'm Alice" person2.sayHello(); // alerts "Hello, I'm Bob" helloFunction(); // alerts "Hello, I'm undefined" (or fails // with a TypeError in strict mode) console.log(helloFunction === person1.sayHello); // logs true console.log(helloFunction === Person.prototype.sayHello); // logs true helloFunction.call(person1); // logs "Hello, I'm Alice" helloFunction.call(person2); // logs "Hello, I'm Bob"
如上例所示, 所有指向sayHello
函數的引用 ,包括 person1
, Person.prototype
, 和 helloFunction
等, 均引用了相同的函數.
console.log(helloFunction === person1.sayHello); // logs true console.log(helloFunction === Person.prototype.sayHello); // logs true
在調用函數的過程中,this的值取決於我們怎麼樣調用函數. 在通常情況下,我們通過一個表達式person1.sayHello()
來調用函數:即從一個對象的屬性中得到所調用的函數。此時this被設置爲我們取得函數的對象(即person1
)。這就是爲什麼person1.sayHello()
使用了姓名“Alice”而person2.sayHello()
使用了姓名“bob”的原因。
然而我們使用不同的調用方法時, this
的值也就不同了。當從變量 helloFunction()
中調用的時候, this
就被設置成了全局對象 (在瀏覽器中即window
)。由於該對象 (非常可能地) 沒有firstName
屬性, 我們得到的結果便是"Hello, I'm undefined"
. (這是鬆散模式下的結果, 在 嚴格模式中,結果將不同(此時會產生一個error
)。 但是爲了避免混淆,我們在這裏不涉及細節) 。另外,我們可以像上例末尾那樣,使用Function#call
(或者Function#apply
)顯式的設置this
的值。
自己的理解:call()
的第一個參數就是this
的值.如果沒用call
,默認this
是那個調用函數的當前的對象.在全局作用域中,就是被隱藏的window
.所以不寫call()
且在全局作用於調用函數的時候,this
就是window
.可以使用call()
或者apply
自己指定this
的指向