web前端開發知識點總結

  • 本文主要針對前端知識點作了彙總,但願幫助一些正在找工做的同窗
  • 本人github網址

1、HTML和CSS

1.css3新屬性

  • transition:過渡 transition:width 2s
  • transform: 旋轉、縮放、移動或者傾斜
  • animation:關鍵幀動畫
  • shadow:陰影 box-shadow
  • border-radius: 圓角

2.rem em

爲了方便計算,時常將在元素中設置font-size值爲62.5%javascript

var win_w=document.body.offsetWidth;
    //定義變量
    var fontSize;
    if(win_w>640){
        fontSize=24;
    }else{
        //若是瀏覽器窗口寬度(這裏的實質就是body寬度)值小於320,取320
        win_w=Math.max(320,win_w);
        fontSize=win_w/320*12
    }
    //設置根元素的大小
    document.getElementsByTagName('html')[0].style.fontSize=fontSize+'px';
複製代碼

理想viewport寬度概括起來無非也就320、360、414css

請參考文章

3.浮動

清除浮動的四種方法:html

  1. 額外標籤法(在最後一個浮動標籤後,新加一個標籤,給其設置clear:both;)(不推薦)
  2. 父級添加overflow屬性(父元素添加overflow:hidden)(不推薦)
  3. 使用after僞元素清除浮動(推薦使用)#content:after{content:"";display:block;clear:both;}
  4. 使用before和after雙僞元素清除浮動
  5. 父級設置高度

4.BFC相關知識

BFC觸發方式:前端

  • 根元素,即HTML標籤
  • 浮動元素:float值爲left、right
  • overflow值不爲 visible,爲 auto、scroll、hidden
  • display值爲 inline-block、table-cell、table-caption、table、inline-table、flex、inline-flex、grid、inline-grid
  • 定位元素:position值爲 absolute、fixed

bfc的做用:java

  1. 阻止元素被浮動元素覆蓋
  2. 能夠包含浮動元素
  3. 阻止由於瀏覽器由於四捨五入形成的多列布局換行的狀況
  4. 阻止相鄰元素的margin合併

bfc處理:node

  1. 兄弟級的塊之間,margin這個屬性上下邊距,常常會發生重疊的狀況,以數值大的爲準,而不會相加。
  • 下面一個元素加float浮動 ,同時父元素加bfc 或者
  • 下面一個元素加inline-block
  1. 父子級的塊之間,子級的上下margin會與父級上下margin重疊,以數值大的爲準,而不會相加。

父級加:css3

  • overflow:hidden
  • 加padding
  • 加border

子級加:git

  • position:absolute

5.IE彈性盒子和標準盒子模型

參考文檔github

主要區別在於: content 的包含問題,IE盒子模型content包含padding border ,此時的寬度就是content的寬度 標準盒子模型:content不包含其餘任何部分。web

box-sizing:

  • border-box 中,整個 div 的寬、高,包括margin、padding、border。 註解:瀏覽器f12獲取的width爲border,padding,content(js獲取的寬度),可是在頁面現實中佔據的寬度爲margin、padding、border,content(即須要加上margin)。改變border,padding時,content發生變化,但寬高不發生變化(除非到比較大的值時)。(IE盒子模型ie6)
  • content-box 中,整個 div 的寬、高,則不包括上面元素。註解:css設置的寬就是content。而經過js獲取獲取的寬度或者調試工具看到的寬度爲content+border+padding,所以真實的寬度隨着前面三個的變化而增長(標準盒子模型)

6.css層級問題

7.經典佈局

juejin.im/post/5aa252…

2、javascript相關知識

1.javascript基本數據類型

6種原始數據類型:

  • Boolean: 布爾表示一個邏輯實體,能夠有兩個值:true 和 false
  • Number: 用於表示數字類型
  • String: 用於表示文本數據
  • Null: Null 類型只有一個值: null,特指對象的值未設置
  • Undefined: 一個沒有被賦值的變量會有個默認值 undefined
  • Symbol: 符號(Symbols)是ECMAScript第6版新定義的。符號類型是惟一的而且是不可修改的

引用類型:Object(Array 、Reg、 function等等)

2.js類型的判斷:

  • typeof
類型 typeof返回
Undefined undefined
Null object
Boolean boolean
Number number
String string
Object object
Function function
  • instanceof: 用來判斷A 是不是 B的實例,表達式爲 A instanceof B,返回一個Boolean類型的值 instanceof 檢測的是原型,只能用來判斷兩個對象是否屬於實例關係, 而不能判斷一個對象實例具體屬於哪一種類型

  • Object.prototype.toString

console.log(Object.prototype.toString.call(123));    //[object Number]
console.log(Object.prototype.toString.call('123'));    //[object String]
console.log(Object.prototype.toString.call(undefined));    //[object Undefined]
console.log(Object.prototype.toString.call(true));    //[object Boolean]
console.log(Object.prototype.toString.call({}));    //[object Object]
console.log(Object.prototype.toString.call([]));    //[object Array]
console.log(Object.prototype.toString.call(function(){}));    //[object Function]
console.log(Object.prototype.toString.call(null));    //[[object Null]]
複製代碼

3.call、applay、bind方法實現

  • 這三種方法主要是爲了改變this的指向,call和applay的區別主要在於,傳遞的參數不一樣,call的參數主要經過逗號隔開傳遞,而applay的經過第二個參數才用數組形式將,全部參數存於數組中一塊兒傳遞。
  • call/applay跟bind的區別在於,前二者調用後,函數能直接執行,而bind調用後返回的是這個函數,須要再手動調用函數才能執行。
// call apply的實現https://blog.csdn.net/qq_40479190/article/details/78324270
Function.prototype.call = function(context){
	var context = context || window;
	context.fn = this;
	var args = [...arguments].slice(1);
	var result = context.fn(...args);
	delete context.fn;
	return result;
}

Function.prototype.apply = function(context){
	var context = context || window;
	context.fn= this;
	var result;
	if(arguments[1]){
		result = context.fn(...arguments[1]);
	}else{
		result = context.fn();
	}
	delete context.fn;
	return result;
}
Function.prototype.bind = function (context) {
	var that = this;
	return function(){
		return that.apply(context);
	}
}

Function.prototype.bind2 = function(context){
	var that = this;
	var args = Array.prototype.slice.call(arguments,1);//arguments不是真實的數組,因此不能直接調用slice方法,須要用這個方法
	return function(){
		var argslist = [...arguments];//第二參數是調用bind函數後返回的函數再調用的時候傳入的參數
		return that.apply(context,[...args,...argslist]);//之因此也要用return是由於原函數可能有返回值
	}
}
複製代碼

4.async函數的實現

  • async底層主要採用generator來實現,舉個簡單例子:
var fs = require('fs');
var readFile = function(fileName){
	return new Promise((resolve, reject) => {
		fs.readFile(fileName,(error, data) => {
			if(error){
				reject(error);
			}else{
				resolve(data);
			}

		});
	});
}
var gen = function* (){
	var f1 = yield readFile('/etc/sdfsdf');
	var f2 = yield readFile('/etc/sdfsdf');
	console.log(f1.toString());
}
var genFn = gen(); // 調用方法
genFn.next(); // {value:'sdfdf',done:true}

// 改寫成async函數 
var asyncReadfile = async function(){
	var f1 = await readFile('/etc/sdfsdf');
	var f2 = await readFile('/etc/sdfsdf');
}
asyncReadfile();
複製代碼
  • async 函數的優勢相對於Generator:
  1. 內置執行器:generator函數執行必須靠執行器,而async函數自帶執行器,因此async和普通函數的執行如出一轍
  2. 更好的語義。async 和 await,比起星號和 yield,語義更清楚了。async 表示函數裏有異步操做,await 表示緊跟在後面的表達式須要等待結果。
  3. 更廣的適用性co函數庫約定,yield 命令後面只能是 Thunk 函數或 Promise 對象,而 async 函數的 await 命令後面,能夠跟 Promise 對象和原始類型的值(數值、字符串和布爾值,但這時等同於同步操做)。
  • async函數的實現,就是將Generator函數和自動執行器包含在一個函數裏面:
async function fn(args){
	// ...
}
//等同於
function fn(args){
	return spawn(function* (){});
}// spawn爲自動執行器
function spawn(genF){
	// genF爲generator函數
	return new Promise((resolve, reject) => {
		var gen = genF();// generator函數調用
		function step(nextF){
			// 封裝的執行器函數
			try{
				var next = nextF();
			}catch(e){
				return reject(e);
			}
			// 沒有返回錯誤判斷generator的返回結果
			if(next.done){
				// 若是next.done爲true表示generator已經執行完了
				return resolve(next.value);
			}
			// 若是沒有執行完,則執行Promise.resolve(next.value)生成一個Promise對象而後繼續遞歸調用
			Promise.resolve(next.value).then((v) => {
				step(() => {
					return gen.next(v);
				});
			}, (err) => {
				step(() => gen.throw(e));
			});
		}
		step(() => gen.next(undefined));
	});
}
複製代碼

5.函數式編程中compose函數的實現

  • 用於將多個函數合併成並執行
function compose(){
	var args = arguments;
	var start = args.length -1 ;
	return function(){
		var i = start;
		var result = args[start].apply(this,arguments);
		while (i--) result = args[i].call(this, result);
		return result;
	}
}
複製代碼

6.函數節流和防抖

  • 函數防抖:

    在事件被觸發n秒後再次執行回調,若是在n秒內又被觸發,則從新計時(函數防抖就是法師發技能的時候要吟唱,技能讀條沒完再按技能就會從新讀條)

    • 應用場景:

      • search搜索聯想,用戶不斷輸入值時,用防抖節約請求資源
      • window出發resize的時候,不斷的調整瀏覽器窗口大小會不斷的觸發這個事件,用防抖來讓其觸發一次
// 防抖debounce

// 初版
function debounce(func, wait){
	var timeout;
	return function(){
		clearTimeout(timeout);
		timeout = setTimeout(func, wait);
	}
}

// this
function debounce(func,wait){
	let timeoutNumber;
	return function() {
		let that = this;
		clearTimeout(timeoutNumber);
		timeoutNumber = setTimeout(function(){
			func.applay(that);
		},wait);
	}
}

// 可能在執行的過程帶事件,因此須要傳遞參數
function debounce(func,wait){
	var timeoutNumber;
	return function() {
		let args = arguments;
		clearTimeout(timeoutNumber);
		timeoutNumber = setTimeout(() => {
			func.apply(this,args);
		},await);
	}
}

// 當即執行,一開始就執行下來
function debounce(func,wait, immediate) {
	var timeout;
	var result;
	return function(){
		var that = this;
		var args = arguments;
		if (timeout) {
			clearTimeout(timeout);
		}
		if(immediate){
			var callNow = timeout; // 有表示已經執行過了
			timeout = setTimeout(() => {
				timeout = null;
			}, wait);
			if(callNow){
				result = func.applay(that,args);
			}
		} else {
			timeout = setTimeout(() => {
				result = func.applay(that,args);
			}, wait);
		}
		return result; // 函數的返回值
	}
}

// 取消
function debounce(func,wait, immediate) {
	var timeout;
	var result;
	var debound = function(){
		var that = this;
		var args = arguments;
		if (timeout) {
			clearTimeout(timeout);
		}
		if(immediate){
			var callNow = timeout; // 有表示已經執行過了
			timeout = setTimeout(() => {
				timeout = null;
			}, wait);
			if(callNow){
				result = func.applay(that,args);
			}
		} else {
			timeout = setTimeout(() => {
				result = func.applay(that,args);
			}, wait);
		}
		return result; // 函數的返回值
	}
	debound.cancel = function(){
		clearTimeout(timeout);
		timeout = null;
	};
	return debound;
}
複製代碼
  • 函數節流:

    規定在一個單位時間內,只能觸發一次函數,若是這個單位時間內觸發屢次函數,只有一次生效(我的理解:函數節流就是fps遊戲的射速,就算一直按着鼠標射擊,也只會在規定射速內射出子彈。)

    • 應用場景
      • 鼠標不斷觸發點擊觸發,mousedown單位時間內只觸發一次
      • 監聽滾動事件,好比是否滑動到底部自動加載更多,用throttle來判斷
// 利用時間戳來實現節流函數
function throttle(func,wait){
	var previous=0;
	var that = 0;
	return function(){
		var now=+ new Date();
		args = arguments;
		if(now - previous > wait){
			func.apply(that, args);
			previous = now;
		}
	}
}
const throttle2 = function(fn, delay) {
	let preTime = Date.now()
  
	return function() {
		const context = this
		let args = arguments
		let doTime = Date.now()
		if (doTime - preTime >= delay) {
			fn.apply(context, args)
			preTime = Date.now()
		}
	}
  }
// 利用定時器來實現
function throttle(func,wait){
	var timeout;
	return function(){
		var args = arguments;
		if(!timeout){
			timeout = setTimeout(() => {
				time = null;
				func.apply(this, args);
			},wait);
		}
	}
}
const throttle = function(fn,delay) {
	let timer = null
  
	return function() {
	  const context = this
	  let args = arguments
	  if(!timer) {
		timer = setTimeout(() => {
		  fn.apply(context,args) 
		  clearTimeout(timer) 
		},delay)
	  }
	}
  }

//第三版
function throttle(func,wait){
	var timeout,context,args,result;
	var previous = 0;
	
	var later = function(){
		previous = + new Date();
		timeout = null;
		func.apply(context, wait);
	}
	return function(){
		var now = + new Date();
		var remaintime = wait - (now - previous);
		context = this;
		args = arguments;
		if(remaintime <= 0 || remaintime > wait){
			if (timeout){
				clearTimeout(timeout);
				timeout = null;
			}
			previous = now;
			func.apply(context,args);
		} else if(!timeout){
			timeout = setTimeout(later, remaintime);
		}
	}
}

function throttle(method, mustRunDelay) {
    let timer,
        args = arguments,
        start;
    return function loop() {
        let self = this;
        let now = Date.now();
        if(!start){
            start = now;
        }
        if(timer){
            clearTimeout(timer);
        }
        if(now - start >= mustRunDelay){
            method.apply(self, args);
            start = now;
        }else {
            timer = setTimeout(function () {
                loop.apply(self, args);
            }, 50);
        }
    }
}
function throttle(fn,wait){
	let timeout,
	args,
	start;
	return function (){
		args = arguments;
		let that = this;
		let now=Date.now();
		if(!start){
			start = now;
		}
		if(timeout){
			clearTimeout(timeout);
		}
	}
}
複製代碼

7.深拷貝和淺拷貝

  • 若是一種引用類型的變量,經過賦值的形式傳遞給新的變量,新的變量中的某個屬性發生變化,原來那個變量對應值也會變化,由於引用類型的變量,都是指向某個指針。這樣就出來拷貝的問題。

淺拷貝

  1. Object.assign
let a = {
  age: 1
  }
  let b = Object.assign({}, a);
  a.age = 2;
  console.log(b.age)// 1
複製代碼
  1. ...擴展運算符
let a = {
 age: 1
 }
 b = {...a};
 a.age = 2;
 console.log(b.age);//1
複製代碼
  1. Array.prototype.slice(0)能夠拷貝數組

深拷貝

  • 當對象裏面嵌套對象或者數組時候就須要用深拷貝
  1. JSON.parse(JSON.stringify(object))實現
  • 會忽略undefined
  • 不會序列化函數
  • 不能解決循環引用的對象
  1. 遞歸的實現:
// 數組的淺拷貝: slice concat方法能夠實現
 function clone(arr){
     var new_arr = arr.concat();
     // var new_arr = arr.slice();
     return new_arr;
 }// 此方法只能拷貝沒有嵌套對象或者數組的
 // JSON.stringify();可是不能拷貝函數

 // 淺拷貝的實現
 function shalloeCopy(obj){
     if(typeof obj !== 'object'){
         return;
     }
     var newObj = obj instanceof Array ? [] : {};
     for (var i in obj){
         console.log(i);
         if(obj.hasOwnProperty(i)){
             newObj[i] = obj[i]
         }
     }
     return newObj;
 }
 shalloeCopy({sdf:2,sdfdfd:1});

 // 深拷貝
 function deepClone(obj){
     if(typeof obj !== 'object'){
         return;
     }
     var newObj = obj instanceof Array ? [] : {};
     for(var key in obj){
         if(obj.hasOwnProperty(key)){
             // 防止原型鏈上的屬性
             newObj[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key]
         }
     }
     return newObj;
 }
複製代碼

8.js事件循環

  • 時間隊列執行順序script(主程序代碼)—>process.nextTick—>Promises...——>setTimeout——>setInterval——>setImmediate——> I/O——>UI rendering
  • nodejs中setTimeout() setInterval() setImmeditate() process.nextTick()二者都表明主線程完成後當即執行,其執行結果是不肯定的,多是setTimeout回調函數執行結果在前,也多是setImmediate回調函數執行結果在前,但setTimeout回調函數執行結果在前的機率更大些,這是由於他們採用的觀察者不一樣,setTimeout採用的是相似IO觀察者,setImmediate採用的是check觀察者,而process.nextTick()採用的是idle觀察者。
  • 三種觀察者的優先級順序是:idle觀察者>>io觀察者>check觀察者
  • process.nextTick()在異步隊列以前,主線程以後
  • process.nextTick(),效率最高,消費資源小,但會阻塞CPU的後續調用; setTimeout(),精確度不高,可能有延遲執行的狀況發生,且由於動用了紅黑樹,因此消耗資源大;setImmediate(),消耗的資源小,也不會形成阻塞,但效率也是最低的。

9.extend的實現

function extend(){
	var args = arguments;
	var target = args[0];
	var objs;
	var newObj;
	for(var i = 0; i<args.length;i++){
		objs = args[i];
		if(objs != null){
			for(var name in objs){
				target[name] = objs[name];
			}
		}
	}
}
複製代碼

10.flatten扁平化和函數柯里化

  • 偏函數和柯里化的區別:
    • 偏函數,固定了你函數的某一個或幾個參數,返回一個新的函數,接收剩下的參數, 參數個數多是1個,也多是2個,甚至更多。
    • 柯理化是把一個有n個參數的函數變成n個只有1個參數的函數
//偏函數 n 變成n-1元,只能一個個減小,m跟柯里化的區別
function partial(fn){
	var args = [].slice.call(arguments, 1);
	return function(){
		var newArgs = args.concat([].slice.call(arguments));
		return fn.applay(this,newArgs);
	}
}

// 第二版
function partial(fn){
	var args = [].slice.call(arguments,1);
	return function(){
		var position=0,len = args.length;
		for(var i=0;i<len;i++){
			args[i] = args[i] === _ ? arguments[position++] : args[i]
		}
		while(position < arguments.length) args.push(arguments[position++]);
        return fn.apply(this, args);
	}
}
// flatten扁平化
function flatten(){
	let arr = arguments[0];
	var result = [];
	for(var i=0;i < arr.length;i++){
		if(Array.isArray(arr[i])){
			result = result.concat(flatten(arr[i]));
		}else{
			result.push(arr[i]);
		}
	}
	return result;
}
// toString
function flatten(arr){
	return arr.toString().split(',').map(item => +item);//+item是將字符串轉化成數字,可是數組中有字符串的不行
}

// reduce實現
function flatten(arr){
	return arr.reduce(function(prev,next){
		return prev.concat(Array.isArray(next)?flatten(next):next)
	}, []);
}
複製代碼
  • 函數柯里化
// 初版
function curry(fn){
	var args = [].slice.call(arguments, 1);//最外面的arguments,此處指的的是調用curry函數時候除了第一個函數外剩下的參數
	return function(){
		var newArgs = args.concat([].slice.call(arguments));//此處的arguments和前面的arguments不是一個,此處表示調用curry返回的函數再調用的時候又傳的參數
		return fn.apply(this,newArgs);
	}
}
function add(a, b) {
    return a + b;
}

var addCurry = curry(add, 1, 2);
addCurry() // 3
//或者
var addCurry = curry(add, 1);
addCurry(2) // 3
//或者
var addCurry = curry(add);
addCurry(1, 2) // 3

// 第二版
function sub_curry(fn) {
    var args = [].slice.call(arguments, 1);
    return function() {
        return fn.apply(this, args.concat([].slice.call(arguments)));
    };
}
function curry(fn, length){
	length = length || fn.length; // 判斷fn有多少形參
	var slice = Array.prototype.slice; // arguments是非數組要調用該方法須要應用
	return function(){
		if(arguments.length < length){ // 表示調用柯里化後的函數參數沒有傳完
			var combined = [fn].concat(slice.call(arguments)); // 柯里化後再調函數還須要的參數,與fn合成一個數組
			return curry(sub_curry.apply(this, combined),length - arguments.length); // 總共須要的形參減去用過的形參
		}else{
			// 所調用的形參足夠直接調用
			return fn.apply(this,arguments);
		}
	}
}

// 通用性 適用性 前幾個大量計算
// 1.參數複用性,
// http() https() get() getJson() 

// 2。提早返回
var addEvent = function(el, type, fn ,capture){
	if(window.addEventListener){
		el.addEventListener();
	}else{
		el.atachEvent();
	}
}
addEvent(p,click,callnack,true);
addEvent(p,click,callnack,true);
// 這樣前面的代碼調用了不少次
var addEvent = function(){
	if(window.addEventListener){
		return function(el, type, fn ,capture){
			el.addEventListener();
		}
	}else {
		return function(el, type, fn ,capture){
			el.atachEvent();
		}
	}
}
var elBind = addEvent();

// 3.延遲執行 ,不定參數做爲最後一次調用(空間換時間)

var allScore = 0;
var addScore = function(score){
	// 對分數的判斷 多少個三分 計算里程碑
	allScore += score;
};
addScore(1);
addScore(2);
addScore(3); // 可是這樣每次就加了

// 虛擬緩存,代理緩存
var curryScore = function(fn){
	var _allScore = [];
	return function(){
		if(arguments.length === 0){
			// 表示統計了
			return fn.apply(null, _allScore);
		}else{
			_allScore = _allScore.concat([].slice.call(arguments));
		}
	}
};
var curryAddScore = curryScore(function(){
	for(var i=0;i<arguments.length;i++){
		allScore+=arguments[i]
	}
});
curryAddScore(1);//0
curryAddScore(2);//0
curryAddScore();//3 不傳參數的時候開始執行
複製代碼

11.each的原生實現:

function each(obj, callback){
	var length,i=0;
	if(isArrayLik(obj)){
		length = obj.length;
		for(;i<obj.length;i++){
			let isOut = callback.call(obj[i],i,obj[i]);
			if(isOut === false){
				break;// 跳出循環
			}
		}
	}else{
		for (i in obj){
			let isOut = callback.call(obj[i],i,obj[i]);
			if(isOut === false){
				break;
			}
		}
	}
	return obj;
}
複製代碼

12.promise的實現原理

// 第一種實現
function MyPromise(fn){
	let self = this;
	self.value = null;
	self.error = null;
	self.onFulfilled = null;
	self.onRejected = null;
	function resolve(value){
		self.value = value;
		self.onFulfilled(self.value);
	}
	function reject(err){
		self.error = err;
		self.onRejected(self.error);
	}
	fn(resolve,reject);
}
MyPromise.prototype.then = function(onFulfilled,onRejected){
	this.onFulfilled = onFulfilled;
	this.onRejected = onRejected;
}
module.exports = MyPromise;
複製代碼
  • 增長狀態參數的改進實現:
    // 改進方案
      const PENDING = 'pending';
      const FULFILLED = 'fulfilled';
      const REJECTED = 'rejected';
      function Promise(fn){
          let self = this;
          self.value = null;
          self.error = null;
          self.status = PENDING;
          self.onFulfilled = null;
          self.onRejected = null;
          function resolve(value){
              if(self.status === PENDING){
                  setTimeout(function(){
                      self.status = FULFILLED;
                      self.value = value;
                      self.onFulfilled(self.value);
                  });
              }
          }
          function reject(error){
              if(self.status === PENDING){
                  setTimeout(function(){
                      self.status = REJECTED;
                      self.error = error;
                      self.onRejected(self.error);
                  });
              }
          }
          fn(resolve,reject);
      }
      MyPromise.prototype.then = function(onFulfilled, onRejected) {
          if (this.status === PENDING) {
              this.onFulfilled = onFulfilled;
              this.onRejected = onRejected;
          } else if (this.status === FULFILLED) {
              //若是狀態是fulfilled,直接執行成功回調,並將成功值傳入
              onFulfilled(this.value)
          } else {
              //若是狀態是rejected,直接執行失敗回調,並將失敗緣由傳入
              onRejected(this.error)
          }
          return this;
      }
    複製代碼
  • promise 鏈式
    const PENDING= 'pending';
      const FULFILLED = 'fulfilled';
      const REJECTED = 'rejected';
      function Promise(fn){
          let self = this;
          self.value = null;
          self.error = null;
          self.status = PENDING;
          self.onFulfilledCallbacks = [];
          self.onRejectedCallbacks = [];
          function resolve(value){
              if(self.status === PENDING){
                  setTimeout(() => {
                      self.status = FULFILLED;
                      self.value = value;
                      self.onFulfilledCallbacks.forEach((callback) => {
                          callback(self.value)
                      });
                  },0);
              }
          }
          function reject(error){
              if(self.status === PENDING){
                  setTimeout(()=>{
                      self.status = REJECTED;
                      self.error = error;
                      self.onRejectedCallbacks.forEach((callback) => {
                          callback(slef.error);
                      });
                  },0);
              }
          }
          fn(resolve,reject);
      }
      Promise.prototype.then = function(onFulfilled,onRejected){
          if(this.status === PENDING){
              this.onFulfilledCallbacks.push(onFulfilled);
              this.onRejectedCallbacks.push(onRejected);
          }else if(this.status === FULFILLED){
              onFulfilled(this.value);
          }else {
              onRejected(this.error);
          }
          return this;
      }
    
    複製代碼
    • Promise.all的實現:
    function promiseAll(promises){
          return new Promise(function(resolve, reject){
              if(!(promises instanceof Array)){
                  throw new TypeError('promises must be an Array');
              }
              var len = promises.length;
              var resolveCount = 0;
              var resolvedArray = new Array(len);
              for(var i=0;i<len;i++){
                  (function(i){
                      Promise.resolve(promises[i])
                      .then((value) => {
                          resolveCount++;
                          resolvedArray[i] = value;
                          if(resolveCount == len){
                              return resolve(resolvedArray);
                          }
                      },re => {
                          return reject(re);
                      }).catch((re) => {
                          console.log(re);
                      });
                  })(i)
              }
          });
      }
    複製代碼

13.數組去重

// 數組去重
    function unique(arr){
        var res = [];
        for(var i=0;i<arr.length;i++){
            // 註明,此處能夠用數組方法includes 和indexOf方法來判斷
            for(var j=0;j<res.length;j++){
                if(arrp[j] == res[j]){
                    break;
                }
                if(j === res.length){
                    res.push(arr[i]);
                }
            }
        }
        return res;
    }
    // 排序後再去重
    function unique(arr){
        var res = arr.filter(function(item,index,arr1){
            return arr.indexOf(item) === index;
        });
        return res;
    }
    function unique(arr){
        var obj = {};
        return arr.filter(function(item,index,arr1){
            return obj.hasOwnProperty(typeof item + item) ? false : (obj[item] = true)
        });
    }
複製代碼

14.websocket的實現

  • 通常爲了實時獲取服務端最新數據常採用輪詢的方法,websocket的出現,服務端和客戶端可以實時進行通訊,而不須要斷開鏈接。聊天室常採用這種技術
  • 基本用法:
    var ws;
      var lockReconnect = false;
      var wsUrl = 'ws:xxx.1.1.1';
      function initEventHandle() {
          ws.onclose = function() {
              reconnet();
          };
          ws.onerror = function(){
              reconnect();
          };
          ws.onopen = function() {
              heartChect.reset().start();
          };
          ws.onmessage = function () {
              heartChect.reset().start();
          };
      }
      function reconnect(url){
          if(lockReconnect){
              return;
          }
          lockReconnect = true;
          setTimeout(function(){
              createWebSocket(url);
          });
      }
    
    複製代碼
相關文章
相關標籤/搜索