// 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;
}