// promise.all 实现
// promise.all(iterable)返回一个新的promise实例。
// 此实例在iterable参数内全部的promise都fulfilled或者参数中不包含promise时,状态才变成fulfilled;
// 若是参数中有一个失败rejected,此实例回调失败,失败的信息是第一个失败promise的返回结果
Promise.all_ = function(promises) {
return new Promise((resolve, reject) => {
// Array.from()可将可迭代对象转化为数组
promises = Array.from(promises);
if(promises.length===0) {
resolve([]);
} else {
let result = [];
let index = 0;
for(let i=0; i<promises.length; i++) {
// 考虑到promise[i]多是thenable对象也多是普通值
Promise.resolve(promises[i]).then(data => {
result[i] = data;
if(++index===promises.length) {
// 全部的promise状态都是fulfilled,promise.all返回的实例才变成fulfilled状态
resolve(result);
}
}, err => {
reject(err);
return;
})
}
}
})
}
复制代码
3.Promise.race实现
// promise.race
// Promise.race返回的仍然是一个Promise,它的状态与第一个完成的Promise的状态相同;
// 若是传入的参数是不可迭代的,那么将会抛出错误。
Promise.ra_ce = function(promises) {
promises = Array.from(promises);
return new Promise((resolve, reject) => {
if(promises.length===0) {
return;
} else {
for(let i=0; i<promises.length; i++) {
Promise.resolve(promises[i]).then(data => {
resolve(data);
return;
}, err => {
reject(err);
return;
})
}
}
})
}
复制代码
4. call实现
// 模拟思路:
// 将函数设为对象的属性
// 执行该函数
// 删除该函数
Function.prototype.call2 = function (context) {
// 将函数设为对象的属性,改变this指向(传null的时候,this指向window)
context = context || window;
context.fn = this;
// 传参并执行函数,用一个数组来接收不定长参数
var args = [];
for(var i = 1; i < arguments.length; i ++){
args.push('arguments['+i+']');
}
var result = eval('context.fn(' + args + ')');
//删除该函数
delete context.fn;
return result;
}
复制代码
5. apply实现
// 模拟apply()方法的实现
Function.prototype.apply2 = function(context,arr){
context = context || window;
context.fn = this;
var result;
if(!arr){
result = context.fn()
}else{
var args = [];
for(var i = 0; i < arr.length; i++){
args.push('arr[' + i + ']')
}
result = eval('context.fn(' + args + ')')
}
delete context.fn;
return result;
}
复制代码
6. bind实现
// 模拟bind的实现
// bind() 方法会建立一个新函数。当这个新函数被调用时,bind() 的第一个参数将做为它运行时的 this,以后的一序列参数将会在传递的实参前传入做为它的参数。
// 1.返回一个函数
// 2.能够传入参数
// 传参时注意:函数能够只传一个参数,而后在执行返回的函数时再继续传参
// 3.bind函数能够用new来建立对象,至关于把原函数看成一个构造器,即当bind返回的函数做为构造函数的时候,bind指定的this失效了
// 4.调用bind的不是函数时要报错
Function.prototype.bind2 = function(context){
if(typeof this !== "function"){
throw new Error("")
}
var self = this;
var args = Array.prototype.slice.call(arguments,1);
var fNOP = function(){}
var fBound = function(){
var bindArgs = Array.prototype.slice.call(arguments);
self.apply(self instanceof fNOP ? this : context,args.concat(bindArgs));
}
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
}
复制代码
7. 继承方法
// 构造函数继承
function Person1(name) {
this.name = name;
}
function Student1(name, age) {
Person1.call(this, name);
this.age = age;
}
var s1 = new Student1("xuhanlin");
console.log(s1.name);
// 原型链继承
function Person2() {
this.name = "renyuan";
}
function Student2(age) {
this.age = age;
}
Student2.prototype = new Person2();
var s2 = new Student2();
console.log(s2.name);
// 组合继承
function Person3() {
this.name = "renyuan";
}
function Student3() {
Person3.call(this);
this.age = "18";
}
Student3.prototype = new Person3();
var s3 = new Student3();
console.log(s3.name, s3.age);
复制代码
8.闭包
// 闭包实现倒计时
for(var i = 10; i > 0; i--){
(function(i){
setTimeout(() => {
console.log(i);
},(10-i)*1000)
})(i)
}
复制代码
9.防抖
function debounce(func,wait){
var timeout;
return function(){
var context = this;
var args = arguments;
clearTimeout(timeout);
timeout = setTimeout(function(){
func.apply(context,args);
},wait);
}
}
复制代码
10.节流
// 使用时间戳
// 当触发事件的时候,咱们取出当前的时间戳,而后减去以前的时间戳(最一开始值设为 0 )
// 若是大于设置的时间周期,就执行函数,而后更新时间戳为当前的时间戳,
// 若是小于,就不执行。
function throttle(func,wait){
return function(){
var context = this;
var args = arguments;
var previous = 0;
var now = +new Date();
if(now - previous > wait){
func.apply(context,args);
previous = now;
}
}
}
// 设置定时器
function throttle(func,wait){
var timeout;
return function(){
var context = this;
var args = arguments;
if(!timeout){
timeout = setTimeout(function(){
timeout = null;
func.apply(context,args)
},wait);
}
}
}
复制代码
11.new实现
function create(Con, ...args) {
let obj = {}
Object.setPrototypeOf(obj, Con.prototype)
//或者 obj.__proto__ = Con.prototype
let result = Con.apply(obj, args)
return result instanceof Object ? result : obj
}
复制代码
12.数组去重
var array = [1,1,'1'];
// 方法一:indexOf()
// 建立一个新数组,遍历原数组,用indexOf判断原数组中的值是否已经存在,不存在就push进去
function unique(arr){
var res = [];
for(let item of arr){
if(res.indexOf(item) === -1){
res.push(item);
}
}
return res;
}
// 方法二:排序后去重
function unique(arr){
var res = [];
var newArr = arr.sort();
for(let i=0; i<newArr.length; i++){
if(newArr[i] !== newArr[i+1]){
res.push(newArr[i]);
}
}
return res;
}
// 方法三:利用Set的惟一性
function unique(arr){
return Array.from(new Set(arr));
}
// 方法四:Map
function unique (arr) {
const map = new Map()
return arr.filter((a) => !map.has(a) && map.set(a, 1))
}
console.log(unique(array));
复制代码
13.数组扁平化
var arr = [1, [2, [3, 4]]];
// 方法一:循环数组,若是里面仍是数组,递归调用扁平化方法
function flatten(arr) {
var result = [];
for (let i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
result = result.concat(flatten(arr[i]));
} else {
result.push(arr[i])
}
}
return result;
}
// 方法一的改进写法
function flatten(arr) {
return arr.reduce(function (pre, item) {
return pre.concat(Array.isArray(item) ? flatten(item) : item)
}, []);
}
// 方法二:toString(),它的一个缺点是改变了元素的类型,只适合于数组中元素都是整数的状况
function flatten(arr) {
return arr.toString().split(",").map(function (item) {
return +item;
})
}
console.log(flatten(arr));
复制代码
14.柯里化
15.快速排序
// 快速排序
// 找到一个基准数,比基准数小的放左边,比基准数大的放右边
// 对左右区间不断重复这个过程
var quickSort = function(arr){
if(arr.length <= 1){
return arr;
}
const pivotIndex = Math.floor(arr.length / 2); //任意基准数索引
const pivot = arr.splice(pivotIndex,1)[0]; //找到对应的基准数
const left = [];
const right = [];
for(let i=0; i<arr.length; i++){
if(arr[i] < pivot){
left.push(arr[i]);
}else{
right.push(arr[i]);
}
}
return quickSort(left).concat([pivot], quickSort(right));
}
const arr = [98, 42, 25, 54, 15, 3, 25, 72, 41, 10, 121];
console.log(quickSort(arr));
复制代码
16.冒泡排序
// 冒泡排序
// 两两相邻元素对比,若是前一个比后一个大,就日后移,一轮比较下来,最大的数到了最后一个
// 重复这个步骤
function bubbleSort(arr) {
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
const temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
return arr;
}
var arr = [10, 14, 8, 5, 88];
console.log(bubbleSort(arr));
复制代码
17.深浅拷贝
// 实现浅拷贝
// 遍历对象,而后把属性和属性值都放到一个新对象里
var shallowCopy = function(obj) {
// 只拷贝对象
if (typeof obj !== 'object') return;
// 根据obj的类型判断是新建一个数组仍是对象
var newObj = obj instanceof Array ? [] : {};
// 遍历obj,而且判断是obj的属性才拷贝
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = obj[key];
}
}
return newObj;
}
// 实现深拷贝
// 在拷贝的时候判断一下属性值的类型,若是是对象,再递归拷贝一下
var deepCopy = function(obj){
if(typeof(obj) !== "object") return;
var newObj = obj instanceof Array ? [] : {};
for(let key in obj){
if(obj.hasOwnProperty(key)){
newObj[key] = typeof obj[key] === "object" ? deepCopy(obj[key]) : obj[key];
}
}
return newObj;
}