这篇文章记录我写在线我的简历过程当中学习的知识
完整代码(暂未完成)
预览地址javascript
英文官网html
模块化:把对应功能放到块里面,这个块能够是文件,或者div或者别的等等github
将js分红不一样的几个模块后,而后使用文件引入,可是会出现问题:若是使用var
声明变量,那么就会成为全局变量,这样容易覆盖.面试
在ES6以前,只有函数里面才有局部变量.
若是只用花括号包起来,那么在C++或者JAVA里面就是局部变量,可是JS里面会变量提高,提高到当前函数的最高地方,因此仍然是全局变量.segmentfault
因此若是想用局部变量,解决方法是把它放到一个函数中,而后当即执行,这样这个函数内部的变量就是局部变量.也不会被相同名字的全局变量覆盖.闭包
不加感叹号就会语法错误,不会执行.因此得加一个感叹号,取反,就会运行后面的代码,执行后面的函数.虽然改变了返回值,可是咱们不须要返回值.因此改变了也无所谓mvc
因此接下来咱们将全部本身分离出来的单个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
),那么 函数+函数外的变量,就是 闭包.
闭包做用:
若是没有当即执行函数来模块化,那么这个闭包毫无心义,由于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()
就至关于当即执行了,由于我声明了一个函数,并且当即执行了
这就是闭包
例如在<script src="./js/init_Swiper.js"></script><!-- 初始化Swiper>标签 -->
这个模块中咱们初始化了一个Swiper
这个而且对.swiper-container
这个div进行操做,.swiper-container
这个div就是 VIEW(用户能够看到的东西).
这个div就是init-swiper这个模块的view.
明白这个以后咱们将view单独分离出来
也将剩下的几个js模块进行修改
例如<script src="./js/sticky-navbar.js"></script>
view就是要告诉js,html中的哪一块是我要操做的东西
MVC中的C用来控制/操做view
以topNavBar为例
将要作的操做写成controller函数,并把要操做的view当作参数传进去,实现对view的控制/操做
进一步的改进:
须要注意:
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
!
原本:
修改后:
修改以后的先后对比
结构很是清晰有条理,将整个要作的事层次分明得分为几个部分
这样代码就不会显得混乱了,controller对view的操做被有条理地分开,有初始化view,绑定view事件,激活这个view,不激活这个view等等对view的操做
controller全部的属性就是对view的全部操做!!!这就是mvc里的c的意义