一、問答
(一)、寫出 構造函數模式、混合模式、模塊模式、工廠模式、單例模式、發布訂閱模式的范例。
//單例模式范例
var Car = (function(){
var instance;
function init() {
//私有的變量和函數
var speed = 0;
return {
//定義公共的屬性和方法
getSpeed: function(){
return speed;
},
setSpeed: function( s ){
speed = s;
}
};
}
return {
getInstance: function() {
if (!instance) {
instance = init();
}
return instance;
}
};
}());
var car = Car.getInstance();
var car2 = Car.getInstance();
car === car2;
1、工廠模式:
//工廠模式 ---通過函數創造一個對象 將其return出來
function createPeople(age,name,sex) {
var o= new Object();
o.age=age;
o.name=name;
o.sex=sex;
return o;
}
var p1=createPeople(18,"zhangsan","M"),
p2=createPeople(20,"lisi","F");
console.log(p1,p2)
2、構造函數模式:
function People(age,name) {
this.age=age;
this.name=name;
this.sayName=function () {
console.log("I am",this.name)
}
}
var p1=new People("1","gouzao");
3、混合模式
function People(name,age) {
this.name=name;
this.age=age;
}
People.prototype.sayAge=function () {
console.log("my age is",this.age)
};
function Students(name,age,teacherName) {
this.teacherName=teacherName;
People.call(this,name,age);
}
Students.prototype=Object.create(People.prototype);
Students.prototype.constructor=Students;
Students.prototype.sayHi=function () {
console.log("Hi! I am student and my name is"+this.name)
};
var student1= new Students("混合",11,"teache11"),
student2= new Students("混合2",22,"teache22");
4、模塊模式:
var People=(function () {
var name="laomingzi";
return{
changeName: function (newName) {
name=newName;
},
sayName:function () {
console.log(name)
}
}
}());
People.sayName();
People.changeName("xinmingzi");
People.sayName();
// 常見形式
var Car=(function () {
var carName="奔馳";
function sayCarName() {
console.log(carName)
}
return{
sayNameFunc:sayCarName
}
}());
Car.sayNameFunc()
模塊模式相對其他模式來說,安全性會有所提升,例如上面的例子,我們不能夠在外面直接訪問carName這個變量;
模塊模式其實使得js具有一定的封裝功能;
5、單例模式:
var Singleton = (function () {
var instantiated;
function init() {
/*這里定義單例代碼*/
return {
publicMethod: function () {
console.log('hello world');
},
publicProperty: 'test'
};
}
return {
getInstance: function () {
if (!instantiated) {
instantiated = init();
}
return instantiated;
}
};
})();
/*調用公有的方法來獲取實例:*/
Singleton.getInstance().publicMethod();
// var danli=(function() {
// var instant;
// function init() {
// return {
// publicMethod: function(){
// console.log("我是單例模式")
// },
// publicOtherProto:"我是單例模式的OtherProto"
// }
// }
// return{
// getInstance:function () {
// if (!instant){
// instant=init();
// }
// return instant;
// }
// }
//
// }());
// danli.getInstance().publicMethod();
再舉個單例模式例子:
var SingletonTester = (function () {
//參數:傳遞給單例的一個參數集合
function Singleton(args) {
//設置args變量為接收的參數或者為空(如果沒有提供的話)
var args = args || {};
//設置name參數
this.name = 'SingletonTester';
//設置pointX的值
this.pointX = args.pointX || 6; //從接收的參數里獲取,或者設置為默認值
//設置pointY的值
this.pointY = args.pointY || 10;
}
//實例容器
var instance;
var _static = {
name: 'SingletonTester',
//獲取實例的方法
//返回Singleton的實例
getInstance: function (args) {
if (instance === undefined) {
instance = new Singleton(args);
}
return instance;
}
};
return _static;
})();
var singletonTest = SingletonTester.getInstance({ pointX: 5 });
console.log(singletonTest.pointX); // 輸出 5
其實單例一般是用在系統間各種模式的通信協調上。
6、發布訂閱模式
//無傳參模式
EventCenter=(function () {
var events={};
return{
on:function (evt,handle) {
events[evt]=events[evt]||[];
events[evt].push(handle);
},
fire:function (evt) {
if (!events[evt]){ console.log("未綁定此事件"); return}
for(var i=0;i<events[evt].length;i++){
events[evt][i]()
}
},
unbind:function (evt) {
delete events[evt];
}
}
}())
//有參數模式
EventCenter=(function () {
var events={};
return{
on:function (evt,handle) {
events[evt]=events[evt]||[];
events[evt].push({handle:handle});
},
fire:function (evt,arg) {
if (!events[evt]){ console.log("未綁定此事件"); return}
for(var i=0;i<events[evt].length;i++){
events[evt][i].handle(arg)
}
},
unbind:function (evt) {
delete events[evt];
}
}
}());
(二)、使用發布訂閱模式寫一個事件管理器,可以實現如下方式調用
EventManager.on('text:change', function(val){
console.log('text:change... now val is ' + val);
});
EventManager.fire('text:change', '饑人谷');
EventManager.off('text:change');
EventManager=(function () {
var events={};
return{
on:function (evt,handle) {
events[evt]=events[evt]||[];
events[evt].push(handle); //{事件1:[函數1,函數2]}
},
fire:function (evt) {
if (!events[evt]){ console.log("未綁定此事件"); return}
for(var i=0;i<events[evt].length;i++){
events[evt][i]([].slice.call(arguments,1))
}
},
off:function (evt) {
delete events[evt];
}
}
}());
運行結果:
Paste_Image.png
二、代碼
(一)、寫一個函數createTimer,用于創建計時器,創建的計時器可分別進行計時「新增」。
ps: 1. 計時器內部寫法參考前面的任務中Runtime的寫法; 2. 體會工廠模式的用法
function createTimer(){
//todo..
}
var timer1 = createTimer();
var timer2 = createTimer();
timer1.start();
for(var i=0;i<100;i++){
console.log(i);
}
timer2.start();
for(var i=0;i<100;i++){
console.log(i);
}
timer1.end();
timer2.end();
console.log(timer1.get());
console.log(timer2.get());
代碼如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
function createTimer(){
var startTime,
endTime,
difference;
var timer={
start: function () {
startTime=Date.now();
return startTime
},
end: function () {
endTime=Date.now();
return endTime
},
get:function () {
difference=endTime-startTime;
return difference
}
};
return timer
}
var timer1 = createTimer();
var timer2 = createTimer();
timer1.start();
for(var i=0;i<100;i++){
console.log(i);
}
timer1.end();
alert("timer1的執行時間是"+timer1.get());
timer2.start();
for(var i=0;i<1000;i++){
console.log(i);
}
timer2.end();
alert("timer2的執行時間是"+timer2.get());
</script>
</body>
</html>
(二)、封裝一個曝光加載組件,能實現如下方式調用
//$target 是 jquery 對象
// 當窗口滾動時,如果$target 出現在可見區域,執行回調函數里面的代碼,且在回調函數內,$(this)代表$target
Expouse.bind($target, function(){
console.log($(this)); // $target
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="http://cdn.bootcss.com/jquery/1.11.2/jquery.min.js"></script>
<style>
li{
height: 30px;
background-color: aqua;
}
</style>
</head>
<body>
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li class="target"> i am target</li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<script>
$(window).on("scroll",function () {
var $target=$(".target");
function isVisible($node) {
var scrollH=$(window).scrollTop(),
$nodeOffsetH=$node.offset().top,
$nodeHeight=$node.outerHeight(true),
windowH=$(window).height();
if ((scrollH+windowH)>$nodeOffsetH &&(scrollH+windowH)<($nodeHeight+$nodeOffsetH) ){
return true
}else {return false}
}
Expouse=(function(){
function bind(evt,callback) {
callback.call(evt)
}
return {
bind:bind
}
}());
if (isVisible($target)){
Expouse.bind($target, function(){
console.log($(this)); // $target
});
}
});
</script>
</body>
</html>
// 當窗口滾動時,如果$target 出現在可見區域,執行回調函數里面的代碼,且在回調函數內,$(this)代表$target。 僅執行一次回調函數,下次$target 曝光不再執行
Expourse.one($target, function(){
console.log($(this)); // $target
})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="http://cdn.bootcss.com/jquery/1.11.2/jquery.min.js"></script>
<style>
li{
height: 30px;
background-color: aqua;
}
</style>
</head>
<body>
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li class="target"> i am target</li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<script>
// //$target 是 jquery 對象
// // 當窗口滾動時,如果$target 出現在可見區域,執行回調函數里面的代碼,且在回調函數內,$(this)代表$target
// Expouse.bind($target, function(){
// console.log($(this)); // $target
// });
$(window).on("scroll",function () {
var $target=$(".target");
if ($target.data("isrun")){
return
}
function isVisible($node) {
var scrollH=$(window).scrollTop(),
$nodeOffsetH=$node.offset().top,
$nodeHeight=$node.outerHeight(true),
windowH=$(window).height();
if ((scrollH+windowH)>$nodeOffsetH &&(scrollH+windowH)<($nodeHeight+$nodeOffsetH) ){
return true
}else {return false}
}
Expouse=(function(){
function bind(evt,callback) {
callback.call(evt)
}
return {
bind:bind
}
}());
if (isVisible($target)){
Expouse.bind($target, function(){
console.log($(this)); // $target
});
$target.data("isrun",true)
}
});
</script>
</body>
</html>
(三)、封裝一個 輪播插件,分別使用對象方式和 jquery插件方式來調用
// 要求:html 里有多個carousel,當調用時啟動全部的 carousel
//方式1
//通過插件的方式啟動所有輪播
$('.carousel').carousel();
//方式2
//通過創建對象的方式啟動所有輪播
$('.carousel').each(function(){
new Carousel($(this));
});
a、 插件方法:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>27-1無限輪播</title>
<style>
ul,li{
list-style: none;
}
*{
margin: 0;
padding: 0;
}
.ct-img>li{
float: left;
width: 310px;
height: 210px;
display: none;
}
li img{
width: 310px;
height: 210px;
}
.clearfix:after{
content: "";
display: block;
clear: both;
}
.ct-bottom>li{
border-bottom: 5px solid #555;
float: left;
cursor: pointer;
width: 20px;
margin: 0 5px;
border-radius: 2px;
}
.ct-bottom{
position: absolute;
top: 180px;
left: 95px;
}
.ct{
position: relative;
}
a.change{
text-decoration: none;
font-size: larger;
font-weight: 900;
background-color: #666;
color: #fff;
display: inline-block;
vertical-align: middle;
padding: 15px;
width: 10px;
height: 10px;
line-height: 10px;
border-radius: 25px;
opacity: 0.7;
}
a.pre{
position: absolute;
left: 10px;
top: 80px;
}
a.next{
position: absolute;
left: 250px;
top: 80px;
}
a.change:hover{
background-color: #444;
}
</style>
<script type="text/javascript" src="http://gc.kis.scr.kaspersky-labs.com/09DC0C47-7E28-5643-A354-E60E2E2E8CBA/main.js" charset="UTF-8"></script></head>
<body>
<div id="wrap">
<div class="ct">
<ul class="clearfix ct-img">
<li data-nub="0"><a href="#"></a></li>
<li data-nub="1"><a href="#"></a></li>
<li data-nub="2"><a href="#"></a></li>
<li data-nub="3"><a href="#"></a></li>
</ul>
<ul class="ct-bottom clearfix">
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<a href="####" class="pre change"> < </a>
<a href="####" class="next change"> > </a>
</div>
<div class="ct">
<ul class="clearfix ct-img">
<li data-nub="0"><a href="#"></a></li>
<li data-nub="1"><a href="#"></a></li>
<li data-nub="2"><a href="#"></a></li>
<li data-nub="3"><a href="#"></a></li>
</ul>
<ul class="ct-bottom clearfix">
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<a href="####" class="pre change"> < </a>
<a href="####" class="next change"> > </a>
</div>
<div class="ct">
<ul class="clearfix ct-img">
<li data-nub="0"><a href="#"></a></li>
<li data-nub="1"><a href="#"></a></li>
<li data-nub="2"><a href="#"></a></li>
<li data-nub="3"><a href="#"></a></li>
</ul>
<ul class="ct-bottom clearfix">
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<a href="####" class="pre change"> < </a>
<a href="####" class="next change"> > </a>
</div>
</div>
<script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
/* 自定義jQuery方法(開發jQuery插件常用此方法) 其實 $.fn === $.prototype */
$.fn.allGo = function() {
this.each(function () {
var $me=$(this),
$ctImg=$me.find(".ct-img"),
$ctBottom=$me.find(".ct-bottom"),
$next=$me.find(".next"),
$pre=$me.find(".pre"),
$ctBottomLi=$me.find(".ct-bottom>li"),
clock=false,
cur=0;
show(0);
setInterval(function () {
playNext()
}, 2000);
function show(num) {
if (clock) {
return;
}
clock = true;
$ctBottom.children().eq(num).css("border-bottom-color", "white");
$ctBottom.children().eq(num).siblings().css("border-bottom-color", "#555");
$ctImg.children().eq(num).siblings().css("display", "none");
$ctImg.children().eq(num).fadeOut(500);
$ctImg.children().eq(num).fadeIn(500, function () {
clock = false
});
cur = num;
return cur;
}
function playNext() {
var nextNum = cur + 1;
if (nextNum === 4) {
show(0)
}
else show(nextNum)
}
$next.on("click", function () {
playNext();
});
$pre.on("click", function () {
playPre();
});
function playPre() {
var preNum = cur - 1;
if (preNum === -1) {
show(3)
}
else show(preNum)
}
$ctBottomLi.on("click", function () {
var $cur = $(this),
indexNum = $cur.index();
show(indexNum);
});
});
};
// $(".ct").each(function () {
// $(this).allGo();
// });
$('.ct').allGo();
</script>
</body>
</html>
b、創建對象方法:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>27-1無限輪播</title>
<style>
ul,li{
list-style: none;
}
*{
margin: 0;
padding: 0;
}
.ct-img>li{
float: left;
width: 310px;
height: 210px;
display: none;
}
li img{
width: 310px;
height: 210px;
}
.clearfix:after{
content: "";
display: block;
clear: both;
}
.ct-bottom>li{
border-bottom: 5px solid #555;
float: left;
cursor: pointer;
width: 20px;
margin: 0 5px;
border-radius: 2px;
}
.ct-bottom{
position: absolute;
top: 180px;
left: 95px;
}
.ct{
position: relative;
}
a.change{
text-decoration: none;
font-size: larger;
font-weight: 900;
background-color: #666;
color: #fff;
display: inline-block;
vertical-align: middle;
padding: 15px;
width: 10px;
height: 10px;
line-height: 10px;
border-radius: 25px;
opacity: 0.7;
}
a.pre{
position: absolute;
left: 10px;
top: 80px;
}
a.next{
position: absolute;
left: 250px;
top: 80px;
}
a.change:hover{
background-color: #444;
}
</style>
<script type="text/javascript" src="http://gc.kis.scr.kaspersky-labs.com/09DC0C47-7E28-5643-A354-E60E2E2E8CBA/main.js" charset="UTF-8"></script></head>
<body>
<div id="wrap">
<div class="ct">
<ul class="clearfix ct-img">
<li data-nub="0"><a href="#"></a></li>
<li data-nub="1"><a href="#"></a></li>
<li data-nub="2"><a href="#"></a></li>
<li data-nub="3"><a href="#"></a></li>
</ul>
<ul class="ct-bottom clearfix">
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<a href="####" class="pre change"> < </a>
<a href="####" class="next change"> > </a>
</div>
<div class="ct">
<ul class="clearfix ct-img">
<li data-nub="0"><a href="#"></a></li>
<li data-nub="1"><a href="#"></a></li>
<li data-nub="2"><a href="#"></a></li>
<li data-nub="3"><a href="#"></a></li>
</ul>
<ul class="ct-bottom clearfix">
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<a href="####" class="pre change"> < </a>
<a href="####" class="next change"> > </a>
</div>
<div class="ct">
<ul class="clearfix ct-img">
<li data-nub="0"><a href="#"></a></li>
<li data-nub="1"><a href="#"></a></li>
<li data-nub="2"><a href="#"></a></li>
<li data-nub="3"><a href="#"></a></li>
</ul>
<ul class="ct-bottom clearfix">
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<a href="####" class="pre change"> < </a>
<a href="####" class="next change"> > </a>
</div>
</div>
<script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
function Carousel($node) {
this.$node=$node;
var $me=this.$node,
$ctImg=$me.find(".ct-img"),
$ctBottom=$me.find(".ct-bottom"),
$next=$me.find(".next"),
$pre=$me.find(".pre"),
$ctBottomLi=$me.find(".ct-bottom>li"),
clock=false,
cur=0;
show(0);
setInterval(function () {
playNext()
}, 2000);
function show(num) {
if (clock) {
return;
}
clock = true;
$ctBottom.children().eq(num).css("border-bottom-color", "white");
$ctBottom.children().eq(num).siblings().css("border-bottom-color", "#555");
$ctImg.children().eq(num).siblings().css("display", "none");
$ctImg.children().eq(num).fadeOut(500);
$ctImg.children().eq(num).fadeIn(500, function () {
clock = false
});
cur = num;
return cur;
}
function playNext() {
var nextNum = cur + 1;
if (nextNum === 4) {
show(0)
}
else show(nextNum)
}
$next.on("click", function () {
playNext();
});
$pre.on("click", function () {
playPre();
});
function playPre() {
var preNum = cur - 1;
if (preNum === -1) {
show(3)
}
else show(preNum)
}
$ctBottomLi.on("click", function () {
var $cur = $(this),
indexNum = $cur.index();
show(indexNum);
});
}
$('.ct').each(function(){
new Carousel($(this));
})
</script>
</body>
</html>
另:JavaScript模式相關書籍
1、JavaScript模式 https://book.douban.com/subject/11506062/
2、JavaScript設計模式 https://book.douban.com/subject/3329540/
3、JavaScript設計模式與開發實踐 https://book.douban.com/subject/26382780/
**本文版權歸本人即簡書筆名:該賬戶已被查封 所有,如需轉載請注明出處。謝謝! *