深拷贝
JSON.parse(JSON.stringify(object)) 有局限性,会忽略 undefined 和 symbol
function isArray(arr) {
return Object.prototype.toString.call(arr) === "[object Array]";
}
function deepCopy(obj) {
let result;
if (isArray(obj)) {
result = [];
} else {
result = {};
}
for (let attr in obj) {
if (typeof obj[attr] === "object") {
result[attr] = arguments.callee(obj[attr]);
} else {
result[attr] = obj[attr];
}
}
return result;
}
new
function create(func, args) {
let obj = {}; //1.创建一个新对象;
obj.__proto__ = func.prototype; //2.设置新对象的_proto_属性指向构造函数的prototype
let result = func.call(obj, ...args); //3.让构造函数的this指向新对象,并执行构造函数(为新对象添加属性)
return result instanceof Object ? result : obj; 4.//确保返回值为对象
}
instanceof
通过判断对象的原型链中是不是能找到类型的 prototype
function myInstanceof(left, right) {
let prototype = right.prototype;
left = left.__proto__;
while (true) {
if (left === null || left === undefined)
//直到对象原型为 null,因为原型链最终为 null
return false;
if (prototype === left) return true;
left = left.__proto__;
}
}
防抖
function antiShake(fn, delay) {
var timer;
return function() {
clearTimeout(timer);
timer = setTimeout(function() {
fn();
}, delay);
};
}
节流
function throttle(fn, delay) {
var flag = true;
return function() {
if (!flag) {
return;
}
flag = false;
setTimeout(function() {
fn();
flag = true;
}, delay);
};
}
bind
Function.prototype.myBind = function(context, ...arr1) {
if (typeof this !== "function") {
throw new TypeError("Bind must be called on a function");
}
let This = this;
context = context || window;
return function(...arr2) {
let arr = arr1.concat(arr2);
// 因为返回了一个函数,我们可以 new,new 的优先级高于 bind
if (this instanceof This) {
return new This(...arr);
}
This.call(context, ...arr);
};
};
function foo(n1, n2, n3, n4) {
console.log(this);
console.log(n1, n2, n3, n4);
}
foo.myBind(document, 3)(4, 5, 6);
call
Function.prototype.call = function(context, ...args) {
context = context || window;
context.func = this;
let res = context.func(...args); //getValue.call(a, 'yck', '24') => a.fn('yck', '24')
delete context.func;
return res;
};
apply
Function.prototype.apply = function(context, args) {
context = context || window;
context.func = this;
let res = context.func(...args);
delete context.func;
return res;
};
jsonP
如果服务端收到请求,返回的是 bar({message:’hello’}),这样的话在服务端就可以把数据通过函数执行传参的方式实现数据传递
function jsonP(url, cbName, cb) {
let script = document.createElement("script");
script.src = url;
window[cbName] = cb;
document.body.appendChild(script);
}
jsonP("http://www.b.com/20190902/jsonp.php?callback=bar", "bar", function(data) {
console.log(data);
});
简易版 promise
class MyPromise {
constructor(fn) {
this.resolveArr = [];
this.rejectArr = [];
this.state = "pending";
let resolveFn = () => {
if (this.state === "pending") {
this.state = "fulfilled";
setTimeout(() => {
for (let i = 0; i < this.resolveArr.length; i++) {
this.resolveArr[i]();
}
}, 0);
}
};
let rejectFn = () => {
if (this.state === "pending") {
this.state = "rejected";
setTimeout(() => {
for (let i = 0; i < this.rejectArr.length; i++) {
this.rejectArr[i]();
}
}, 0);
}
};
fn(resolveFn, rejectFn);
}
then(cb) {
if (this.state === "pending") {
this.resolveArr.push(cb);
return this;
}
}
catch(cb) {
if (this.state === "pending") {
this.rejectArr.push(cb);
return this;
}
}
}
function foo() {
return new MyPromise(function(resolve, reject) {
setTimeout(() => {
resolve();
// reject();
}, 1000);
});
}
foo()
.then(function() {
console.log(1);
})
.catch(function() {
console.log(2);
})
.then(function() {
console.log(3);
});