new的实现
function Otaku (name, age) {
this.name = name;
this.age = age;
this.habit = 'Games';
}
Otaku.prototype.strength = 60;
Otaku.prototype.sayYourName = function () {
console.log('I am ' + this.name);
}
function new1(){
var obj = {};
var Constructor = [].shift.call(arguments);
obj.__proto__ = Constructor.prototype;
var ret = Constructor.apply(obj,arguments);
return typeof ret === 'object' ? ret : obj;
}
//测试
var a = new1(Otaku,'Kevin',18)
a.sayYourName(); //I am Kevin
console.log(a.name) //Kevin
console.log(a.age) //18
console.log(a.habit) //Games
console.log(a.strength) //60
call的实现
var value = 2;
var obj = {
value: 1
}
function bar(name, age) {
console.log(this.value);
return {
value: this.value,
name: name,
age: age
}
}
Function.prototype.call2=function(context){
var context = context || window;
var args = [...arguments].slice(1);
var result = null;
context.fn=this;
result = context.fn(...args);
delete context.fn;
return result;
}
//测试
bar.call(null); //2
console.log(bar.call2(obj, 'kevin', 18));
// 1
// Object {
// value: 1,
// name: 'kevin',
// age: 18
// }
apply的实现
Function.prototype.apply2=function(context,arr){
var context = context || window;
context.fn = this;
var result = null;
if(!arr){
result = context.fn();
} else{
result = context.fn(...arr);
}
delete context.fn;
return result;
}
var value = 2;
var obj = {
value: 1
}
function bar(name, age) {
console.log(this.value);
return {
value: this.value,
name: name,
age: age
}
}
//测试
bar.apply2(null); //2
console.log(bar.apply2(obj, ['kevin', 18]));
// 1
// Object {
// value: 1,
// name: 'kevin',
// age: 18
// }
bind的实现
Function.prototype.bind2 = function(context){
if(typeof this !== 'function'){
throw new Error('this is not a function')
}
var args = Array.prototype.slice.call(arguments,1);
var self = this;
var FNOP = function(){};
var fbound = function(){
var bindArgs = Array.prototype.slice.call(arguments);
return self.apply(this instanceof FNOP ? this:context, args.concat(bindArgs));
}
FNOP.prototype = self.prototype;
fbound.prototype = new FNOP();
return fbound;
}
浅拷贝
function shallowCopy(obj){
if(typeof obj !== 'object'){return}
var newObj = obj instanceof Array ? [] : {};
for(var key in obj){
if(obj.hasOwnProperty(key)){
newObj[key] = obj[key];
}
}
return newObj;
}
深拷贝
var deepCopy = function(obj){
if(obj === null || typeof obj !== 'object'){return}
var newObj = obj instanceof Array ? [] : {};
for(var key in obj){
if(obj.hasOwnProperty(key)){
newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key];
}
}
return newObj
}
节流
节流有两种方式,一种是时间戳,一种是定时器
1、时间戳
// 在规定的时间间隔内只能执行一次事件处理函数,而不是像防抖,只有最后一次有效。
// 比如滚动页面,是每隔一个时间间隔就发松一次请求,而不是在最后停止滚动时才发送一次请求。
const throttle = function(fn, interval){
let last = 0;
return function (...args){
let now = new Date();
if(now - last < interval)return;
last = now;
fn.apply(this, args)
}
}
2、定时器
function throttle(fn, interval){
let timer = null;
return function(){
let context = this;
let args = [...arguments];
if(!timer){
let timer = setTimeout(function(){
fn.apply(context, args);
timer = null;
}, interval)
}
}
}
防抖
// 不管事件处理函数触发了多少次,只有最后一次有效,在设定时间到达之前被触发,则重新延时。
const debounce = function(fn, delay){
let timer = null;
return function(...args){
let context = this;
if(timer){clearTimeout(timer)}
timer = setTimeout(function(){
fn.apply(context,args)
},delay)
}
}
加强版节流
function throttle(fn, interval){
let timer = null;
let last = 0;
return function(){
let context = this;
let args = [...arguments];
let now = Date.now();
if(now - last < interval){
clearTimeout(timer);
setTimeout(function(){
last = now;
fn.apply(context, args);
}, interval)
}else {
last = now;
fn.apply(context, args);
}
}
}
Promise.all实现
let MyPromiseAll = function(promises){
let result = [];
let promiseCount = 0;
let promiseLen = promises.length;
return new Promise(function(resolve,reject){
for(let val of promises){
Promise.resolve(val).then(function(res){
result.push(val);
promiseCount++;
if(promiseCount === promiseLen){
return resolve(result)
}
},function(err){
throw reject(err)
})
}
})
}