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);
          });
      }
    
    复制代码
相关文章
相关标签/搜索