模塊化、MVC裏的V和C、閉包與立即執行函數的使用
這篇文章記錄我寫在線個人簡歷過程中學習的知識
完整代碼(暫未完成)
預覽地址
輪播Swiper組件的使用
模塊化
模塊化:把對應功能放到塊裏面,這個塊可以是文件,或者div或者別的等等
立即執行函數的使用
將js分成不同的幾個模塊後,然後使用文件引入,但是會出現問題:如果使用var
聲明變量,那麼就會成爲全局變量,這樣容易覆蓋.
在ES6之前,只有函數裏面纔有局部變量.
如果只用花括號包起來,那麼在C++或者JAVA裏面就是局部變量,但是JS裏面會變量提升,提升到當前函數的最高地方,所以仍然是全局變量.
所以如果想用局部變量,解決方法是把它放到一個函數中,然後立即執行,這樣這個函數內部的變量就是局部變量.也不會被相同名字的全局變量覆蓋.
不加感嘆號就會語法錯誤,不會執行.所以得加一個感嘆號,取反,就會運行後面的代碼,執行後面的函數.雖然改變了返回值,但是我們不需要返回值.所以改變了也無所謂
所以接下來我們將所有自己分離出來的單個js文件,都使用立即執行函數!function(){}.call()
包起來
ps:
ES6模塊
閉包的使用
下面的例子都使用立即執行函數隔離作用域
如果兩個模塊之間需要交流,例如在第一個模塊上初始化,在第二個模塊上使用
方法一:使用window
比如兩個模塊
module1.js和module2.js都被引入一個html文件裏
//module1.js
!function(){
var person = window.person = {
name:"frank",
}
//局部變量person和全局變量person用的是同一個地址
}.call()
雖然不同變量,但是是同樣的地址
//module2.js
!function(){
var person = person;//即var person = window.person;
console.log(person);
}.call();
這樣不同模塊間就可以通信,但這種方法不好.
方法二:使用閉包
始終不知道person的全部信息
,只能知道age的信息,且只能做一些它允許你操作的事情,這樣module1就會對局部變量person有一個掌控.不會出現有人把person變成-1的情況,因爲他訪問不到age,他只能去GrowUp,除此之外沒有能訪問到的方法.
//module1.js
!function(){
var person = {
name:"mataotao",
age:18,
};
window.mataotaoGrowUp = function(){
person.age+=1;
return person.age;
};
}.call();
//module2.js
!function(){
var newAge = window.mataotaoGrowUp();
console.log(newAge);//19
}.call();
閉包在哪裏?
如果一個函數訪問了函數外的變量(mataotaoGrowUp()
使用了person.age
),那麼 函數+函數外的變量,就是 閉包.
閉包作用:
- 用來 隱藏數據細節 (不告訴你多少歲但是你可以讓他漲一歲,隱藏了age 的細節和name)
- 可以用來 做訪問控制 (只能訪問到age,無法訪問到name)
如果沒有立即執行函數來模塊化,那麼這個閉包毫無意義,因爲person直接使全局變量,所有的函數都可以訪問到,並且修改也無法隱藏數據細節
立即執行函數+閉包 實現對象細節的封裝的方法
面試官會將上面的module1做如下修改(實際本質不變)
//module1.js
var accessor = function(){//這是一個返回了匿名函數的函數,accessor-訪問器
var person = {
name:"mataotao",
age:18,
};
return function(){
person.age+=1;
return person.age;
};
}
var growUp = accessor();//執行accessor得到一個GrowUp函數
//growUp現在是一個全局變量了
growUp();
實際growUp()
就相當於立即執行了,因爲我聲明瞭一個函數,而且立即執行了
這就是閉包
MVC的V和C
View就是能看到的東西
例如在<script src="./js/init_Swiper.js"></script><!-- 初始化Swiper>標籤 -->
這個模塊中我們初始化了一個Swiper
這個並且對.swiper-container
這個div進行操作,.swiper-container
這個div就是 VIEW(用戶可以看到的東西).
這個div就是init-swiper這個模塊的view.
明白這個之後我們將view單獨分離出來
分離view
也將剩下的幾個js模塊進行修改
例如<script src="./js/sticky-navbar.js"></script>
view就是要告訴js,html中的哪一塊是我要操作的東西
Controller就是控制View的方法
MVC中的C用來控制/操作view
以topNavBar爲例
將要做的操作寫成controller函數,並把要操作的view當做參數傳進去,實現對view的控制/操作
進一步的改進:
需要注意:
- 對象的函數裏的this,就是對象本身`controller.init(view);
//相當於controller.init.call(controller,view);//this就是當前對象`
`this.bindEvents();
//相當於this.bindEventS.call(this)`,這裏的this就是init函數裏call的controller,所以這個this是轉過來了,也是對象本身
繼續優化,分離代碼
如果我們要做其他的事情,比如把激活和不激活這個導航分離,不要寫在bindEvents裏了,繼續在對象裏添加操作的函數bind(this)
後,就是把controller綁定到這個函數的this
上,把這個函數的this
由window變成controller,之後this.active();
和this.deactive();
這兩個this
就變成了controller了
bind
方法用於將函數體內的this
綁定到某個對象,然後返回一個新函數。
bind()使用方法
這裏的bind()
就是將函數體內的this
綁定到了controller,函數體內的this
就是controller了
如果不用bind()
也可以用箭頭函數()=>{}
,箭頭函數本身是沒有this的.所以如果在箭頭函數用this
,那麼就是箭頭函數外面的離它最近的this
!
對輪播的js模塊使用controller進行優化
本來:
修改後:
修改之後的前後對比
結構非常清晰有條理,將整個要做的事井井有條得分爲幾個部分
對當頁跳轉的緩動動畫也進行controller的優化
總結
這樣代碼就不會顯得混亂了,controller對view的操作被有條理地分開,有初始化view,綁定view事件,激活這個view,不激活這個view等等對view的操作
controller所有的屬性就是對view的所有操作!!!
這就是mvc裏的c的意義