// 各類小的 原生的JS語法和註解
for (var i = 0; i < 3; i++) {
setTimeout(function () {
console.log('i=' + i);
}, 1000)
}
// 這是常常遇到的,可是這裏結果會打印3次 i=3; 由於setTimeout是一個異步執行隊列任務,因此,當執行console.log(i)的時候,for早已經循環完畢,因此i=3會被打印3次。現作出以下修改
// 1:閉包存值
for (var i = 0; i < 3; i++) {
(function (i) {
setTimeout(function () {
console.log('i=' + i);
}, 1000)
})(i)
}
//2:塊級做用域存值
for (let i = 0; i < 3; i++) {
setTimeout(function () {
console.log('i=' + i);
}, 1000)
}
//能夠利用閉包,作以下修改,把每次的i 保存在一個封閉的環境,這裏採用了匿名的自執行函數(也能夠用顯示函數)。 當時間函數順着做用域鏈查找時,會先找到封閉在閉包環境重的i,
//因此下列結果打印就是 i=1,i=2,i=3
/*
apply/call
區別:第一個參數都死this上下文,參數,appl是全部參數爲數組(不肯定有多少個參數),call是肯定參數個數,
obj1.fn.call(obj2,arg1,arg2,arg3) == obj1.fn.apply(obj2,arguments) ; - - - obj2調用obj1下的fn 方法
*/
var obj1 = {
fn() {
this.b = '456';
}
},
obj2 = {};
obj1.fn.apply(obj2, []);
console.log(obj1.b); // undefined
console.log(obj2.b); // 456
/*
函數節流 :
如:window.onresize/mousemove/文件上傳等事件,須要大量的重複觸發,而顯然對於用戶,不必如此頻繁的去觸發事件。
這是就能夠利用setTimeout來作函數節流,即按照咱們要求(例:每1000毫秒執行一次)。
*/
var throttle = function (fn, interval) {
var _self = fn,
timer, firstTime = true;
return function () {
var args = arguments,
_me = this;
if (firstTime) {
_self.apply(_me, args);
return firstTime = false;
}
if (timer) {
console.log(timer)
return false;
}
timer = setTimeout(function () {
_self.apply(_me, args);
clearTimeout(timer);
timer = undefined;
}, interval || 1000)
}
};
window.onresize = throttle(() => {
console.log(1232);
}, 1000)
/*
* 單例模式:保證一個類僅有一個實例,而且提供一個能訪問天的全局訪問點
* 通用的惰性單例模式:聽從單一職責,惟一性,使用時才建立
*
*/
var getSignle = (fn) => {
// 通用單例方法
var result;
return () => {
return result || (result = fn.apply(this.arguments));
}
};
var createLogin = () => {
var div = document.createElement('div');
div.innerHTML = '我是登錄框';
div.style.display = 'none';
document.body.appendChild(div);
return div;
}
var createSignleLogin = getSignle(createLogin);
document.getElementById('loginBtn').onclick = () => {
var loginDiv = createSignleLogin();
loginDiv.style.display = "block";
}
/**
* 備忘錄模式:以靜態形式在內存中對對象數據進行存儲,這樣可對對象數據進行恢復。
*
* */
function Memento(){
this.storage={};
}
Memento.prototype.saveState=function(key,obj){
console.log(this)
this.storage[key]=JSON.stringify(obj);
}
Memento.prototype.restoreState=function(key){
var output={};
if(this.storage.hasOwnProperty(key)){
output= JSON.parse(this.storage[key]) ;
}
return output;
}
var memento=new Memento(),user={name:'leo',age:23};
memento.saveState('user',user);
console.log(memento.storage['user']);
user={
name:'CD-leo',age:'18',weight:'80kg'
};
console.log(user);
user=memento.restoreState('user');
console.log(memento.storage['user']);
/**
* 發佈/訂閱模式:經過觸發事件,去觸發訂閱的回調事件,VUE的響應式就是基於此模式(不單單限於)。
*
* */
function Public() {
this.handlers = {};
}
Public.prototype = {
// 訂閱事件
on: function(eventType, handler){
var self = this;
if(!(eventType in self.handlers)) {
self.handlers[eventType] = [];
}
self.handlers[eventType].push(handler);
return this;
},
// 觸發事件(發佈事件)
emit: function(eventType){
var self = this;
var handlerArgs = Array.prototype.slice.call(arguments,1);
for(var i = 0; i < self.handlers[eventType].length; i++) {
self.handlers[eventType][i].apply(self,handlerArgs);
}
return self;
},
// 刪除訂閱事件
off: function(eventType, handler){
var currentEvent = this.handlers[eventType];
var len = 0;
if (currentEvent) {
len = currentEvent.length;
for (var i = len - 1; i >= 0; i--){
if (currentEvent[i] === handler){
currentEvent.splice(i, 1);
}
}
}
return this;
}
};
var Publisher = new Public();
//訂閱事件a
Publisher.on('a', function(data){
console.log(1 + data);
});
Publisher.on('a', function(data){
console.log(2 + data);
});
//觸發事件a
Publisher.emit('a', '我是第1次調用的參數');
Publisher.emit('a', '我是第2次調用的參數');