1.引出
1.js的作用域问题:访问全局变量和var定义的局部变量,闭包的作用
<script>
function demo01(){
var num = 19;
age = 20;
}
demo01();
console.log(num); //var定义的num不能被访问到,他是函数内的局部变量
console.log(age);//可以被访问到,这是一个全局变量
function Demo(){
var hello = "hello";
return function(){
// 闭包!!!
// 1.读取局部变量 2.保存当前状态
}
}
Demo();
console.log(hello);
</script>
2.解决方法
(1)定义一个对象用来读取
var infoObj = {
name:"iwen",
age:20,
sex:"男"
}
// 不至于直接挂载到全局:var一个对象
console.log(infoObj.age);
infoObj.age = 30;
console.log(infoObj.age); //age被修改
缺点:在定义的对象之外可以任意修改对象中的内容
(2)使用自执行函数
(function(){ //自执行函数
function userInfo(){
var name = "iwen";
var age = 20;
return {
name:name,
age:age
}
}
console.log(userInfo().age);
var info = userInfo()
console.log(info.name);
})();
缺点:作用域独立,name、age在函数外无法被修改,但也读不到了
(3)模块!
2.模块
- 设计模式规范
开闭原则:对扩展开放,对修改关闭
var一个对象,对象里是一个自执行函数,外界可以访问,但是不能修改
var module = (function(){ var infoObj = { name:'iwen', age:20 } function getName(){ if(!infoObj.name){ return; } return infoObj.name; } function getAge(){ if(!infoObj.age){ return; } return infoObj.age }
2.提供一个修改方法:模块中只能添加,不能修改
function setAge(age){
if(age){
infoObj.age = age;
}
}
function setName(name){
infoObj.name = name
}
/*
公有方法:getName,getAge,setAge
私有方法:infoObj
*/
return{
getName:getName,
getAge:getAge,
setAge:setAge,
setName:setName
}
})();
console.log(module.getName());
console.log(module.getAge());
module.setAge(30);
console.log(module.getAge());
// module.setName("ice"); // 错误
3.扩展:当出现多个模块
- 扩展(放大模式):
<script type="text/javascript"> var module1 = (function(){ function Demo1(){ console.log("Demo1"); } function Demo2(){ console.log("Demo2"); } return { Demo1:Demo1, Demo2:Demo2 } })() // 对于程序而言,一个module肯定不能完成所有的事情 // 如果现在需要扩展? var module2 = (function(module1){ //第一种方式 :module2 中调用module1 function Demo3(){ console.log(module1.Demo1()) } //第二种方式:module2 本身 function M2Demo(){ console.log("M2Demo") } // 第三种方式:直接挂载到module1身上 module1.Demo4 = function(){ console.log("M2M1Demo4") } return{ Demo3:Demo3, M2Demo:M2Demo, module1:module1 } })(module1); module2.Demo3() module2.M2Demo() module2.module1.Demo4(); </script>
2.放宽大模式:解决了出现多个模块,需要调用前一个模块时,前一个模块为空的问题
var module1 = (function(){
var hello = "hello";
return {}
})();//必须有一个return,否则会显示undefined
module1 = null;
var module2 = (function(module1){
module1.demo = function (){
console.log("demo")
};
return{
module1:module1
}
})(module1||{}); //存在则使用module1,不存在则变成一个对象,解决的没有return值或者赋值为空的情况
console.log(module2.module1.demo())
4.js文件之间的隔离与调用:require.js
Nodejs: common.js规范,js文件之间会互相调用,所以需要文件与文件之间的隔离
CommonJs通过nodeJs发扬光大,每个js文件就是一个模块,每个模块有单独的作用域。模块以module.exports为出口,输出一个对象。使用require方法读取文件,并返回其内部的module.exports对象。
5. requirejs:
1.require介绍:
(1).模块化
(2).帮我们管理文件依赖
(3).管理引入js文件
2.引入require:在js/libs中引入require.js文件,在js中写一个main.js文件
<script data-main="js/main.js" src="js/libs/require.js"></script>
3.配置main.js
// 配置文件
requirejs.config({
// 基础路径
baseUrl: 'js/',
// 映射
// .js可以省略
paths:{
"index":"apps/index",
"getname":"apps/getname",
"jquery":"libs/jquery-3.2.1"
}
})
requirejs(["index","getname","jquery"],function(index,getname,$){
// 主入口文件
// 调用
index.init();
})
6.模块js文件的定义define:三种方式
1.定义模块
define({
name:"iwen",
age:20
})
2.函数式定义
define(function(){
var demo = 10;
function demo(){
}
})
3.存在依赖的函数式定义:依赖注入可以使不同js文件产生联系
define(["jquery"],function($){
console.log($ );
})
注意:
问题:
每一个js文件都需要遵循define模块定义规范
那么为什么jquery不需要遵循呢?
答:jquery本身就遵循了define定义规范
如果引入的第三方需不需要遵循?
答:需要,如果不遵循的如果使用呢?
如果不遵循,我们需要导出为遵循的方案
7.不遵循define模块定义:shim模块
1.swiper.js框架:一个分页器,包含了swiper.min.css和swiper.min.js,写法参考官网的API
2.main.js中的写法:
> requirejs.config({ baseUrl:"js/", paths:{
> "jquery":"lib/jquery-3.2.1",
> "swiper":"lib/swiper.min",
> "index":"app/index" },
// 为那些没有使用define()来声明依赖关系、设置
// 模块的"浏览器全局变量注入"型脚本做依赖和导出配置
shim:{
> "swiper":{
> deps:["jquery"], //依赖于jQuery
> exports:"swiper" //通过swiper导出
> } } })
>
> requirejs(["jquery","swiper","index"],function($,swiper,index){ })
8.require.js的应用案例:百度音乐
1.requirejs使用场景
(1).后端渲染:require(路由)
(2).某个页面或者主页面具有很多js文件引入
2.思路:index.js为主入口文件+view.js为试图文件+config.js为配置文件+http.js为网络请求文件